diff --git a/factor/parser/Tuple.java b/factor/parser/Tuple.java index db6a2f5c26..7d287bc0ac 100644 --- a/factor/parser/Tuple.java +++ b/factor/parser/Tuple.java @@ -51,6 +51,7 @@ public class Tuple extends FactorParsingDefinition String tupleName = (String)next; reader.intern(tupleName,true); reader.intern("<" + tupleName + ">",true); + reader.intern(tupleName + "?",true); for(;;) { diff --git a/library/math/matrices.factor b/library/math/matrices.factor index 925907c841..3b1bf6c4fd 100644 --- a/library/math/matrices.factor +++ b/library/math/matrices.factor @@ -110,7 +110,7 @@ M: col-seq nth col-seq-matrix ; #! for being added or subtracted. over matrix-rows over matrix-rows = >r over matrix-cols over matrix-cols = r> and [ - "Matrix dimensions do not match" + "Matrix dimensions do not match" throw ] unless ; : +dimensions ( matrix -- rows cols ) @@ -128,7 +128,7 @@ M: matrix v* ( m m -- m ) matrix+/- v* ; : *check ( matrix matrix -- matrix matrix ) over matrix-rows over matrix-cols = >r over matrix-cols over matrix-rows = r> and [ - "Matrix dimensions inappropriate for composition" + "Matrix dimensions inappropriate for composition" throw ] unless ; : *dimensions ( m m -- rows cols ) diff --git a/library/syntax/parse-syntax.factor b/library/syntax/parse-syntax.factor index 63578d7b98..f2ca81d36d 100644 --- a/library/syntax/parse-syntax.factor +++ b/library/syntax/parse-syntax.factor @@ -87,7 +87,11 @@ BUILTIN: f 9 ; : f f swons ; parsing #! recursive words. CREATE drop ; parsing -: FORGET: scan-word forget ; parsing +: FORGET: + #! Followed by a word name. The word is removed from its + #! vocabulary. Note that specifying an undefined word is a + #! no-op. + scan "use" get search [ forget ] when* ; parsing : USE: #! Add vocabulary to search path. diff --git a/library/tools/annotations.factor b/library/tools/annotations.factor index 985e8c26e4..83bb9c717b 100644 --- a/library/tools/annotations.factor +++ b/library/tools/annotations.factor @@ -8,26 +8,23 @@ IN: words ! no effect of compiled calls to that word. USING: interpreter kernel lists prettyprint stdio strings test ; -: annotate ( word quot -- ) #! Quotation: ( word def -- def ) +: annotate ( word quot -- | quot: word def -- def ) over >r >r dup word-def r> call r> swap (define-compound) ; inline -: (watch) >r "==> " swap word-name cat2 \ print r> cons cons ; +: (watch) ( word def -- def ) + >r "==> " swap word-name cat2 \ print \ .s r> + cons cons cons ; : watch ( word -- ) #! Cause a message to be printed out when the word is - #! executed. To undo the effect of this, reload the - #! word with \ foo reload. + #! executed. [ (watch) ] annotate ; : break ( word -- ) #! Cause the word to start the code walker when executed. [ nip [ walk ] cons ] annotate ; -: dump ( word -- ) - #! Cause the word to print the stack when executed. - [ nip [ .s ] swap append ] annotate ; - : timer ( word -- ) #! Print the time taken to execute the word when it's called. [ nip [ time ] cons ] annotate ; diff --git a/library/unix/io.factor b/library/unix/io.factor index 79c1510df5..146f4f6f28 100644 --- a/library/unix/io.factor +++ b/library/unix/io.factor @@ -1,8 +1,8 @@ -! Copyright (C) 2005 Slava Pestov. +! Copyright (C) 2004, 2005 Slava Pestov. ! See http://factor.sf.net/license.txt for BSD license. IN: io-internals USING: errors generic hashtables kernel lists math namespaces -sequences strings threads vectors ; +sequences streams strings threads vectors ; ! These let us load the code into a CFactor instance using the ! old C-based I/O. They will be removed soon. @@ -10,8 +10,39 @@ FORGET: can-read-line? FORGET: can-read-count? FORGET: can-write? FORGET: add-write-io-task +FORGET: blocking-read-line +FORGET: blocking-write +FORGET: wait-to-read +FORGET: wait-to-read-line +FORGET: wait-to-write +! Some general stuff +: file-mode OCT: 0600 ; + +: io-error ( n -- ) 0 < [ errno strerror throw ] when ; + +: init-handle ( fd -- ) + F_SETFL O_NONBLOCK 1 sys-fcntl io-error ; + +! Common delegate of native stream readers and writers +TUPLE: port handle buffer error ; + +C: port ( handle buffer -- port ) + [ >r r> set-delegate ] keep + [ >r dup init-handle r> set-port-handle ] keep ; + +: buffered-port 8192 ; + +: >port< dup port-handle swap delegate ; + +: pending-error ( reader -- ) port-error throw ; + +! Associates a port with a list of continuations waiting on the +! port to finish I/O TUPLE: io-task port callbacks ; +C: io-task ( port -- ) [ set-io-task-port ] keep ; + +! Multiplexer GENERIC: do-io-task ( task -- ? ) GENERIC: io-task-events ( task -- events ) @@ -21,29 +52,62 @@ GENERIC: io-task-events ( task -- events ) ! this with the hash-size call. SYMBOL: io-tasks -: file-mode OCT: 0600 ; +: init-io ( -- ) global [ io-tasks set ] bind ; -: io-error ( n -- ) 0 < [ errno strerror throw ] when ; +: io-task-fd io-task-port port-handle ; + +: add-io-task ( callback task -- ) + [ >r unit r> set-io-task-callbacks ] keep + dup io-task-fd io-tasks get 2dup hash [ + "Cannot perform multiple I/O ops on the same port" throw + ] when set-hash ; + +: remove-io-task ( task -- ) + io-task-fd io-tasks get remove-hash ; + +: pop-callback ( task -- callback ) + dup io-task-callbacks uncons dup [ + rot set-io-task-callbacks + ] [ + drop swap remove-io-task + ] ifte ; + +: handle-fd ( fd -- ) + io-tasks get hash dup do-io-task [ + pop-callback call + ] [ + drop + ] ifte ; + +: do-io-tasks ( pollfds n -- ) + [ + dup pick pollfd-nth dup pollfd-revents 0 = [ + drop + ] [ + pollfd-fd handle-fd + ] ifte + ] repeat drop ; + +: init-pollfd ( task pollfd -- ) + over io-task-fd over set-pollfd-fd + swap io-task-events swap set-pollfd-events ; + +: make-pollfds ( -- pollfds n ) + io-tasks get dup hash-size [ + swap >r 0 swap r> hash-values [ + ( n pollfds iotask ) + pick pick pollfd-nth init-pollfd >r 1 + r> + ] each nip + ] keep ; + +: io-multiplex ( -- ) + make-pollfds 2dup 0 sys-poll drop do-io-tasks ; + +! Readers : open-read ( path -- fd ) O_RDONLY file-mode sys-open dup io-error ; -: open-write ( path -- fd ) - O_WRONLY O_CREAT bitor O_TRUNC bitor file-mode sys-open - dup io-error ; - -TUPLE: port handle buffer error ; - -C: port ( handle buffer -- port ) - [ >r r> set-delegate ] keep - [ set-port-handle ] keep ; - -: buffered-port 8192 ; - -: >port< dup port-handle swap delegate ; - -: pending-error ( reader -- ) port-error throw ; - TUPLE: reader line ready? ; C: reader ( handle -- reader ) @@ -96,7 +160,7 @@ C: reader ( handle -- reader ) TUPLE: read-line-task ; -C: read-line-task ( port callbacks -- task ) +C: read-line-task ( port -- task ) [ >r r> set-delegate ] keep ; M: read-line-task do-io-task @@ -127,7 +191,7 @@ M: read-line-task io-task-events ( task -- events ) TUPLE: read-task count ; -C: read-task ( port callbacks -- task ) +C: read-task ( port -- task ) [ >r r> set-delegate ] keep ; M: read-task do-io-task @@ -152,6 +216,38 @@ M: read-task io-task-events ( task -- events ) "reader not ready" throw ] ifte ; +: wait-to-read-line ( port -- ) + dup can-read-line? [ + drop + ] [ + [ + swap add-io-task io-multiplex + ] callcc0 drop + ] ifte ; + +M: reader stream-readln ( stream -- line ) + dup wait-to-read-line read-fin ; + +: wait-to-read ( count port -- ) + 2dup can-read-count? [ + 2drop + ] [ + [ + swap add-io-task io-multiplex + ] callcc0 2drop + ] ifte ; + +M: reader stream-read ( count stream -- string ) + 2dup wait-to-read read-fin ; + +M: reader stream-close ( stream -- ) port-handle sys-close ; + +! Writers + +: open-write ( path -- fd ) + O_WRONLY O_CREAT bitor O_TRUNC bitor file-mode sys-open + dup io-error ; + TUPLE: writer ; C: writer ( fd -- writer ) @@ -173,7 +269,7 @@ C: writer ( fd -- writer ) TUPLE: write-task ; -C: write-task ( port callbacks -- task ) +C: write-task ( port -- task ) [ >r r> set-delegate ] keep ; M: write-task do-io-task @@ -187,8 +283,41 @@ M: write-task io-task-events ( task -- events ) drop write-events ; : write-fin ( str writer -- ) - dup pending-error - >r dup string? [ ch>string ] unless r> >buffer ; + dup pending-error >buffer ; + +: add-write-io-task ( callback task -- ) + dup io-task-fd io-tasks get hash [ + dup write-task? [ + [ + nip io-task-callbacks cons + ] keep set-io-task-callbacks + ] [ + add-io-task + ] ifte + ] [ + add-io-task + ] ifte* ; + +M: writer stream-flush ( stream -- ) + [ + swap add-write-io-task io-multiplex + ] callcc0 drop ; + +M: writer stream-auto-flush ( stream -- ) drop ; + +: wait-to-write ( len port -- ) + tuck can-write? [ drop ] [ stream-flush ] ifte ; + +: blocking-write ( str writer -- ) + over length over wait-to-write write-fin ; + +M: writer stream-write-attr ( string style writer -- ) + nip >r dup string? [ ch>string ] unless r> blocking-write ; + +M: writer stream-close ( stream -- ) + dup stream-flush port-handle sys-close ; + +! Copying from a reader to a writer : can-copy? ( from -- ? ) dup eof? [ read-step ] [ drop t ] ifte ; @@ -207,69 +336,3 @@ M: write-task io-task-events ( task -- events ) ] [ 2drop f ] ifte ; - -: io-task-fd io-task-port port-handle ; - -: add-io-task ( task -- ) - dup io-task-fd io-tasks get 2dup hash [ - "Cannot perform multiple I/O ops on the same port" throw - ] when set-hash ; - -: add-write-io-task ( task -- ) - dup io-task-fd io-tasks get hash [ - dup write-task? [ - [ - >r io-task-callbacks r> io-task-callbacks append - ] keep set-io-task-callbacks - ] [ - add-io-task - ] ifte - ] [ - add-io-task - ] ifte* ; - -: remove-io-task ( task -- ) - io-task-fd io-tasks get remove-hash ; - -: pop-callback ( task -- callback ) - dup io-task-callbacks uncons dup [ - rot set-io-task-callbacks - ] [ - drop swap remove-io-task - ] ifte ; - -: handle-fd ( fd -- ) - io-tasks get hash dup do-io-task [ - pop-callback call - ] [ - drop - ] ifte ; - -: do-io-tasks ( pollfds n -- ) - [ - dup pick pollfd-nth dup pollfd-revents 0 = [ - drop - ] [ - pollfd-fd handle-fd - ] ifte - ] repeat drop ; - -: init-pollfd ( task pollfd -- ) - over io-task-fd over set-pollfd-fd - swap io-task-events swap set-pollfd-events ; - -: make-pollfds ( -- pollfds n ) - io-tasks get dup hash-size [ - swap hash-values [ - dup io-task-fd pick pollfd-nth init-pollfd - ] each - ] keep ; - -: io-multiplexer ( -- ) - make-pollfds dupd 0 sys-poll do-io-tasks ; - -: io-loop ( -- ) io-multiplexer yield io-loop ; - -: init-io ( -- ) - global [ io-tasks set ] bind - [ io-loop ] in-thread ; diff --git a/library/unix/syscalls.factor b/library/unix/syscalls.factor index 8979bbb8f4..5d0ee4846d 100644 --- a/library/unix/syscalls.factor +++ b/library/unix/syscalls.factor @@ -80,6 +80,12 @@ END-STRUCT : sys-close ( fd -- ) "void" "libc" "close" [ "int" ] alien-invoke ; +: F_SETFL 4 ; ! set file status flags +: O_NONBLOCK 4 ; ! no delay + +: sys-fcntl ( fd cmd key value -- n ) + "int" "libc" "fcntl" [ "int" "int" "int" "int" ] alien-invoke ; + : sys-read ( fd buf nbytes -- n ) "ssize_t" "libc" "read" [ "int" "ulong" "size_t" ] alien-invoke ; diff --git a/native/alien.c b/native/alien.c index 6d4ac5d94e..4a9dc29180 100644 --- a/native/alien.c +++ b/native/alien.c @@ -15,7 +15,7 @@ INLINE void* alien_offset(CELL object) return alien->ptr; case BYTE_ARRAY_TYPE: array = untag_byte_array_fast(object); - return array + sizeof(F_ARRAY); + return array + 1; case DISPLACED_ALIEN_TYPE: d = untag_displaced_alien_fast(object); return alien_offset(d->alien) + d->displacement;