Merge branch 'master' of git://factorcode.org/git/factor
commit
863ace7ab3
|
@ -59,6 +59,7 @@ ARTICLE: "assocs-sets" "Set-theoretic operations on assocs"
|
|||
{ $subsection diff }
|
||||
{ $subsection remove-all }
|
||||
{ $subsection substitute }
|
||||
{ $subsection substitute-here }
|
||||
{ $see-also key? } ;
|
||||
|
||||
ARTICLE: "assocs-mutation" "Storing keys and values in assocs"
|
||||
|
@ -266,12 +267,16 @@ HELP: remove-all
|
|||
{ $notes "The values of the keys in the assoc are disregarded, so this word is usually used for set-theoretic calculations where the assoc in question either has dummy sentinels as values, or the values equal the keys." }
|
||||
{ $side-effects "assoc" } ;
|
||||
|
||||
HELP: substitute
|
||||
{ $values { "assoc" assoc } { "seq" "a mutable sequence" } }
|
||||
{ $description "Replaces elements of " { $snippet "seq" } " which appear in as keys in " { $snippet "assoc" } " with the corresponding values, acting as the identity on all other elements." }
|
||||
HELP: substitute-here
|
||||
{ $values { "seq" "a mutable sequence" } { "assoc" assoc } }
|
||||
{ $description "Replaces elements of " { $snippet "seq" } " which appear as keys in " { $snippet "assoc" } " with the corresponding values, acting as the identity on all other elements." }
|
||||
{ $errors "Throws an error if " { $snippet "assoc" } " contains values whose types are not permissible in " { $snippet "seq" } "." }
|
||||
{ $side-effects "seq" } ;
|
||||
|
||||
HELP: substitute
|
||||
{ $values { "seq" sequence } { "assoc" assoc } { "newseq" sequence } }
|
||||
{ $description "Creates a new sequence where elements of " { $snippet "seq" } " which appear as keys in " { $snippet "assoc" } " are replaced by the corresponding values, and all other elements are unchanged." } ;
|
||||
|
||||
HELP: cache
|
||||
{ $values { "key" "a key" } { "assoc" assoc } { "quot" "a quotation with stack effect " { $snippet "( key -- value )" } } { "value" "a previously-retained or freshly-computed value" } }
|
||||
{ $description "If the key is present in the assoc, outputs the associated value, otherwise calls the quotation to produce a value and stores the key/value pair into the assoc." }
|
||||
|
|
|
@ -124,8 +124,14 @@ M: assoc assoc-clone-like ( assoc exemplar -- newassoc )
|
|||
: remove-all ( assoc seq -- subseq )
|
||||
swap [ key? not ] curry subset ;
|
||||
|
||||
: substitute ( assoc seq -- )
|
||||
swap [ dupd at* [ nip ] [ drop ] if ] curry change-each ;
|
||||
: (substitute)
|
||||
[ dupd at* [ nip ] [ drop ] if ] curry ; inline
|
||||
|
||||
: substitute-here ( seq assoc -- )
|
||||
(substitute) change-each ;
|
||||
|
||||
: substitute ( seq assoc -- newseq )
|
||||
(substitute) map ;
|
||||
|
||||
: cache ( key assoc quot -- value )
|
||||
2over at [
|
||||
|
|
|
@ -59,7 +59,7 @@ SYMBOL: bootstrap-time
|
|||
|
||||
default-image-name "output-image" set-global
|
||||
|
||||
"math help compiler tools ui ui.tools io" "include" set-global
|
||||
"math help handbook compiler tools ui ui.tools io" "include" set-global
|
||||
"" "exclude" set-global
|
||||
|
||||
parse-command-line
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
IN: temporary
|
||||
USING: debugger kernel continuations tools.test ;
|
||||
|
||||
[ ] [ [ drop ] [ error. ] recover ] unit-test
|
|
@ -26,7 +26,7 @@ SYMBOL: compiling-word
|
|||
|
||||
SYMBOL: compiling-label
|
||||
|
||||
SYMBOL: compiling-loop?
|
||||
SYMBOL: compiling-loops
|
||||
|
||||
! Label of current word, after prologue, makes recursion faster
|
||||
SYMBOL: current-label-start
|
||||
|
@ -34,7 +34,7 @@ SYMBOL: current-label-start
|
|||
: compiled-stack-traces? ( -- ? ) 36 getenv ;
|
||||
|
||||
: begin-compiling ( word label -- )
|
||||
compiling-loop? off
|
||||
H{ } clone compiling-loops set
|
||||
compiling-label set
|
||||
compiling-word set
|
||||
compiled-stack-traces?
|
||||
|
@ -94,8 +94,8 @@ M: node generate-node drop iterate-next ;
|
|||
: generate-call ( label -- next )
|
||||
dup maybe-compile
|
||||
end-basic-block
|
||||
dup compiling-label get eq? compiling-loop? get and [
|
||||
drop current-label-start get %jump-label f
|
||||
dup compiling-loops get at [
|
||||
%jump-label f
|
||||
] [
|
||||
tail-call? [
|
||||
%jump f
|
||||
|
@ -104,7 +104,7 @@ M: node generate-node drop iterate-next ;
|
|||
%call
|
||||
iterate-next
|
||||
] if
|
||||
] if ;
|
||||
] ?if ;
|
||||
|
||||
! #label
|
||||
M: #label generate-node
|
||||
|
@ -113,17 +113,13 @@ M: #label generate-node
|
|||
r> ;
|
||||
|
||||
! #loop
|
||||
: compiling-loop ( word -- )
|
||||
<label> dup resolve-label swap compiling-loops get set-at ;
|
||||
|
||||
M: #loop generate-node
|
||||
end-basic-block
|
||||
[
|
||||
dup node-param compiling-label set
|
||||
current-label-start define-label
|
||||
current-label-start resolve-label
|
||||
compiling-loop? on
|
||||
dup node-param compiling-loop
|
||||
node-child generate-nodes
|
||||
end-basic-block
|
||||
] with-scope
|
||||
init-templates
|
||||
iterate-next ;
|
||||
|
||||
! #if
|
||||
|
@ -269,5 +265,6 @@ M: #r> generate-node
|
|||
|
||||
! #return
|
||||
M: #return generate-node
|
||||
node-param compiling-label get eq? compiling-loop? get and
|
||||
[ end-basic-block %return ] unless f ;
|
||||
end-basic-block
|
||||
node-param compiling-loops get key?
|
||||
[ %return ] unless f ;
|
||||
|
|
|
@ -504,7 +504,7 @@ M: loc lazy-store
|
|||
: substitute-vregs ( values vregs -- )
|
||||
[ vreg-substitution ] 2map
|
||||
[ substitute-vreg? ] assoc-subset >hashtable
|
||||
[ swap substitute ] curry each-phantom ;
|
||||
[ substitute-here ] curry each-phantom ;
|
||||
|
||||
: set-operand ( value var -- )
|
||||
>r dup constant? [ constant-value ] when r> set ;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
! Copyright (C) 2006, 2007 Daniel Ehrenberg.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: math kernel sequences sbufs vectors io.streams.lines io.streams.plain
|
||||
namespaces unicode.syntax growable strings io classes io.streams.c
|
||||
namespaces unicode growable strings io classes io.streams.c
|
||||
continuations ;
|
||||
IN: io.encodings
|
||||
|
||||
|
@ -19,7 +19,7 @@ SYMBOL: begin
|
|||
over push 0 begin ;
|
||||
|
||||
: push-replacement ( buf -- buf ch state )
|
||||
UNICHAR: replacement-character decoded ;
|
||||
CHAR: replacement-character decoded ;
|
||||
|
||||
: finish-decoding ( buf ch state -- str )
|
||||
begin eq? [ decode-error ] unless drop "" like ;
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
USING: tools.test io.utf16 arrays unicode.syntax ;
|
||||
USING: tools.test io.utf16 arrays unicode ;
|
||||
|
||||
[ { CHAR: x } ] [ { 0 CHAR: x } decode-utf16be >array ] unit-test
|
||||
[ { HEX: 1D11E } ] [ { HEX: D8 HEX: 34 HEX: DD HEX: 1E } decode-utf16be >array ] unit-test
|
||||
[ { UNICHAR: replacement-character } ] [ { BIN: 11011111 CHAR: q } decode-utf16be >array ] unit-test
|
||||
[ { UNICHAR: replacement-character } ] [ { BIN: 11011011 CHAR: x BIN: 11011011 CHAR: x } decode-utf16be >array ] unit-test
|
||||
[ { CHAR: replacement-character } ] [ { BIN: 11011111 CHAR: q } decode-utf16be >array ] unit-test
|
||||
[ { CHAR: replacement-character } ] [ { BIN: 11011011 CHAR: x BIN: 11011011 CHAR: x } decode-utf16be >array ] unit-test
|
||||
|
||||
[ B{ 0 120 216 52 221 30 } ] [ { CHAR: x HEX: 1d11e } encode-utf16be ] unit-test
|
||||
|
||||
[ { CHAR: x } ] [ { CHAR: x 0 } decode-utf16le >array ] unit-test
|
||||
[ { 119070 } ] [ { HEX: 34 HEX: D8 HEX: 1E HEX: DD } decode-utf16le >array ] unit-test
|
||||
[ { UNICHAR: replacement-character } ] [ { 0 BIN: 11011111 } decode-utf16le >array ] unit-test
|
||||
[ { UNICHAR: replacement-character } ] [ { 0 BIN: 11011011 0 0 } decode-utf16le >array ] unit-test
|
||||
[ { CHAR: replacement-character } ] [ { 0 BIN: 11011111 } decode-utf16le >array ] unit-test
|
||||
[ { CHAR: replacement-character } ] [ { 0 BIN: 11011011 0 0 } decode-utf16le >array ] unit-test
|
||||
|
||||
[ B{ 120 0 52 216 30 221 } ] [ { CHAR: x HEX: 1d11e } encode-utf16le ] unit-test
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
USING: io.encodings.utf8 tools.test sbufs kernel io
|
||||
sequences strings arrays unicode.syntax ;
|
||||
sequences strings arrays unicode ;
|
||||
|
||||
: decode-utf8-w/stream ( array -- newarray )
|
||||
>sbuf dup reverse-here <utf8> contents >array ;
|
||||
|
@ -7,7 +7,7 @@ sequences strings arrays unicode.syntax ;
|
|||
: encode-utf8-w/stream ( array -- newarray )
|
||||
SBUF" " clone tuck <utf8> write >array ;
|
||||
|
||||
[ { UNICHAR: replacement-character } ] [ { BIN: 11110101 BIN: 10111111 BIN: 10000000 BIN: 11111111 } decode-utf8-w/stream >array ] unit-test
|
||||
[ { CHAR: replacement-character } ] [ { BIN: 11110101 BIN: 10111111 BIN: 10000000 BIN: 11111111 } decode-utf8-w/stream >array ] unit-test
|
||||
|
||||
[ { BIN: 101111111000000111111 } ] [ { BIN: 11110101 BIN: 10111111 BIN: 10000000 BIN: 10111111 } decode-utf8-w/stream >array ] unit-test
|
||||
|
||||
|
@ -15,7 +15,7 @@ sequences strings arrays unicode.syntax ;
|
|||
|
||||
[ { BIN: 11111000000 } ] [ { BIN: 11011111 BIN: 10000000 } decode-utf8-w/stream >array ] unit-test
|
||||
|
||||
[ { UNICHAR: replacement-character } ] [ { BIN: 10000000 } decode-utf8-w/stream >array ] unit-test
|
||||
[ { CHAR: replacement-character } ] [ { BIN: 10000000 } decode-utf8-w/stream >array ] unit-test
|
||||
|
||||
[ { BIN: 1111000000111111 } ] [ { BIN: 11101111 BIN: 10000000 BIN: 10111111 } decode-utf8-w/stream >array ] unit-test
|
||||
|
||||
|
|
|
@ -37,10 +37,10 @@ GENERIC: optimize-node* ( node -- node/t changed? )
|
|||
over assoc-empty? [
|
||||
2drop
|
||||
] [
|
||||
2dup node-in-d substitute
|
||||
2dup node-in-r substitute
|
||||
2dup node-out-d substitute
|
||||
node-out-r substitute
|
||||
2dup node-in-d swap substitute-here
|
||||
2dup node-in-r swap substitute-here
|
||||
2dup node-out-d swap substitute-here
|
||||
node-out-r swap substitute-here
|
||||
] if ;
|
||||
|
||||
: perform-substitutions ( node -- )
|
||||
|
|
|
@ -113,7 +113,7 @@ optimizer ;
|
|||
] unit-test
|
||||
|
||||
[ f ] [
|
||||
[ [ [ ] map ] map ] dataflow optimize
|
||||
[ [ [ ] map ] map ] dataflow dup detect-loops
|
||||
[ dup #label? swap #loop? not and ] node-exists?
|
||||
] unit-test
|
||||
|
||||
|
@ -146,3 +146,36 @@ DEFER: a
|
|||
[ a ] dataflow dup detect-loops
|
||||
\ b label-is-loop?
|
||||
] unit-test
|
||||
|
||||
DEFER: a'
|
||||
|
||||
: b' ( -- )
|
||||
blah [ b' b' ] [ a' ] if ; inline
|
||||
|
||||
: a' ( -- )
|
||||
blah [ b' ] [ a' ] if ; inline
|
||||
|
||||
[ f ] [
|
||||
[ a' ] dataflow dup detect-loops
|
||||
\ a' label-is-loop?
|
||||
] unit-test
|
||||
|
||||
[ f ] [
|
||||
[ b' ] dataflow dup detect-loops
|
||||
\ b' label-is-loop?
|
||||
] unit-test
|
||||
|
||||
! I used to think this should be f, but doing this on pen and
|
||||
! paper almost convinced me that a loop conversion here is
|
||||
! sound. The loop analysis algorithm looks pretty solid -- its
|
||||
! a standard iterative dataflow problem after all -- so I'm
|
||||
! tempted to believe the computer here
|
||||
[ t ] [
|
||||
[ b' ] dataflow dup detect-loops
|
||||
\ a' label-is-loop?
|
||||
] unit-test
|
||||
|
||||
[ f ] [
|
||||
[ a' ] dataflow dup detect-loops
|
||||
\ b' label-is-loop?
|
||||
] unit-test
|
||||
|
|
|
@ -7,7 +7,7 @@ combinators classes generic.math continuations optimizer.def-use
|
|||
optimizer.backend generic.standard ;
|
||||
IN: optimizer.control
|
||||
|
||||
! ! ! Loop detection
|
||||
! ! ! Rudimentary CFA
|
||||
|
||||
! A LOOP
|
||||
!
|
||||
|
@ -36,7 +36,8 @@ IN: optimizer.control
|
|||
! |
|
||||
! #values
|
||||
!
|
||||
! NOT A LOOP (call to A nested inside another label/loop):
|
||||
! NOT A LOOP (call to A nested inside another label which is
|
||||
! not a loop):
|
||||
!
|
||||
!
|
||||
! #label A
|
||||
|
@ -53,38 +54,70 @@ IN: optimizer.control
|
|||
! | |
|
||||
! #call-label A |
|
||||
! | |
|
||||
! ... ...
|
||||
! #values |
|
||||
! #call-label B
|
||||
! |
|
||||
! ...
|
||||
|
||||
GENERIC: detect-loops* ( node -- )
|
||||
! Mapping word => { node { nesting tail? }+ height }
|
||||
! We record all calls to a label, their control nesting and
|
||||
! whether it is a tail call or not
|
||||
SYMBOL: label-info
|
||||
|
||||
M: node detect-loops* drop ;
|
||||
GENERIC: collect-label-info* ( node -- )
|
||||
|
||||
M: #label detect-loops* t swap set-#label-loop? ;
|
||||
M: #label collect-label-info*
|
||||
[ V{ } clone node-stack get length 3array ] keep
|
||||
node-param label-info get set-at ;
|
||||
|
||||
: not-a-loop ( #label -- )
|
||||
f swap set-#label-loop? ;
|
||||
USE: prettyprint
|
||||
|
||||
: tail-call? ( -- ? )
|
||||
node-stack get
|
||||
dup [ #label? ] find-last drop [ 1+ ] [ 0 ] if* tail
|
||||
[ node-successor #tail? ] all? ;
|
||||
USE: io
|
||||
: detect-loop ( seen-other? label node -- seen-other? continue? )
|
||||
#! seen-other?: have we seen another label?
|
||||
{
|
||||
{ [ dup #label? not ] [ 2drop t ] }
|
||||
{ [ 2dup node-param eq? not ] [ 3drop t t ] }
|
||||
{ [ tail-call? not ] [ not-a-loop drop f ] }
|
||||
{ [ pick ] [ not-a-loop drop f ] }
|
||||
{ [ t ] [ 2drop f ] }
|
||||
} cond ;
|
||||
M: #call-label collect-label-info*
|
||||
node-param label-info get at
|
||||
node-stack get over third tail
|
||||
[ [ #label? ] subset [ node-param ] map ] keep
|
||||
[ node-successor #tail? ] all? 2array
|
||||
swap second push ;
|
||||
|
||||
M: #call-label detect-loops*
|
||||
f swap node-param node-stack get <reversed>
|
||||
[ detect-loop ] with all? 2drop ;
|
||||
M: node collect-label-info*
|
||||
drop ;
|
||||
|
||||
: detect-loops ( node -- )
|
||||
[ detect-loops* ] each-node ;
|
||||
: collect-label-info ( node -- )
|
||||
H{ } clone label-info set
|
||||
[ collect-label-info* ] each-node ;
|
||||
|
||||
! Mapping word => label
|
||||
SYMBOL: potential-loops
|
||||
|
||||
: remove-non-tail-calls ( -- )
|
||||
label-info get
|
||||
[ nip second [ second ] all? ] assoc-subset
|
||||
[ first ] assoc-map
|
||||
potential-loops set ;
|
||||
|
||||
: remove-non-loop-calls ( -- )
|
||||
! Boolean is set to t if something changed.
|
||||
! We recurse until a fixed point is reached.
|
||||
f label-info get [
|
||||
! If label X is called from within a label Y that is
|
||||
! no longer a potential loop, then X is no longer a
|
||||
! potential loop either.
|
||||
over potential-loops get key? [
|
||||
second [ first ] map concat
|
||||
potential-loops get [ key? ] curry all?
|
||||
[ drop ] [ potential-loops get delete-at t or ] if
|
||||
] [ 2drop ] if
|
||||
] assoc-each [ remove-non-loop-calls ] when ;
|
||||
|
||||
: detect-loops ( nodes -- )
|
||||
[
|
||||
collect-label-info
|
||||
remove-non-tail-calls
|
||||
remove-non-loop-calls
|
||||
potential-loops get [
|
||||
nip t swap set-#label-loop?
|
||||
] assoc-each
|
||||
] with-scope ;
|
||||
|
||||
! ! ! Constant branch folding
|
||||
!
|
||||
|
@ -204,7 +237,7 @@ M: #if optimize-node*
|
|||
|
||||
! #label -> C -> #return 1
|
||||
! |
|
||||
! -> #if -> #merge -> #return 2
|
||||
! -> #if -> #merge (*) -> #return 2
|
||||
! |
|
||||
! --------
|
||||
! | |
|
||||
|
@ -218,17 +251,17 @@ M: #if optimize-node*
|
|||
|
||||
! AFTER:
|
||||
|
||||
! #label -> #terminate
|
||||
! #label -> #return 1
|
||||
! |
|
||||
! -> #if -> #terminate
|
||||
! |
|
||||
! --------
|
||||
! | |
|
||||
! A B
|
||||
! | |
|
||||
! -> #if -------> #merge (*) -> #return 2
|
||||
! | \-------------------/
|
||||
! ---------------- |
|
||||
! | | |
|
||||
! A B unreacachable code needed to
|
||||
! | | preserve invariants
|
||||
! #values |
|
||||
! | #call-label
|
||||
! #merge |
|
||||
! #merge (*) |
|
||||
! | |
|
||||
! C #values
|
||||
! |
|
||||
|
@ -282,14 +315,22 @@ M: node add-loop-exit*
|
|||
] [ 2drop f ] if
|
||||
] [ drop f ] if ;
|
||||
|
||||
! M: #loop optimize-node*
|
||||
! dup lift-loop-tail? dup [
|
||||
! last-node >r
|
||||
! dup detach-node-successor
|
||||
! over node-child find-final-if detach-node-successor
|
||||
! [ set-node-successor ] keep
|
||||
! r> set-node-successor
|
||||
! t
|
||||
! ] [
|
||||
! 2drop t f
|
||||
! ] if ;
|
||||
M: #loop optimize-node*
|
||||
dup lift-loop-tail? dup [
|
||||
last-node "values" set
|
||||
|
||||
dup node-successor "tail" set
|
||||
dup node-successor last-node "return" set
|
||||
dup node-child find-final-if node-successor "merge" set
|
||||
|
||||
! #label -> #return
|
||||
"return" get clone-node over set-node-successor
|
||||
! #merge -> C
|
||||
"merge" get clone-node "tail" get over set-node-successor
|
||||
! #values -> #merge ->C
|
||||
"values" get set-node-successor
|
||||
|
||||
t
|
||||
] [
|
||||
2drop t f
|
||||
] if ;
|
||||
|
|
|
@ -266,19 +266,10 @@ HELP: escape
|
|||
{ $description "Converts from a single-character escape code and the corresponding character." }
|
||||
{ $examples { $example "CHAR: n escape CHAR: \\n = ." "t" } } ;
|
||||
|
||||
HELP: next-escape
|
||||
{ $values { "m" "an index into " { $snippet "str" } } { "str" string } { "n" "an index into " { $snippet "str" } } { "ch" "a character" } }
|
||||
{ $description "Helper word for " { $link parse-string } " which parses an escape sequence starting at the " { $snippet "m" } "th index of " { $snippet "str" } "." }
|
||||
{ $errors "Throws a " { $link bad-escape } " if the string contains an invalid escape sequence." } ;
|
||||
|
||||
HELP: next-char
|
||||
{ $values { "m" "an index into " { $snippet "str" } } { "str" string } { "n" "an index into " { $snippet "str" } } { "ch" "a character" } }
|
||||
{ $description "Helper word for " { $link parse-string } " which parses a character starting at the " { $snippet "m" } "th index of " { $snippet "str" } "." } ;
|
||||
|
||||
HELP: parse-string
|
||||
{ $values { "str" "a new " { $link string } } }
|
||||
{ $description "Parses the line until a quote (\"), interpreting escape codes along the way." }
|
||||
{ $errors "Throws an " { $link bad-escape } " if the string contains an invalid escape sequence." }
|
||||
{ $errors "Throws an error if the string contains an invalid escape sequence." }
|
||||
$parsing-note ;
|
||||
|
||||
HELP: still-parsing?
|
||||
|
|
|
@ -119,22 +119,43 @@ M: bad-escape summary drop "Bad escape code" ;
|
|||
{ CHAR: \" CHAR: \" }
|
||||
} at [ bad-escape ] unless* ;
|
||||
|
||||
: next-escape ( m str -- n ch )
|
||||
2dup nth CHAR: u =
|
||||
[ >r 1+ dup 6 + tuck r> subseq hex> ]
|
||||
[ over 1+ -rot nth escape ] if ;
|
||||
SYMBOL: name>char-hook
|
||||
|
||||
: next-char ( m str -- n ch )
|
||||
2dup nth CHAR: \\ =
|
||||
[ >r 1+ r> next-escape ] [ over 1+ -rot nth ] if ;
|
||||
name>char-hook global [
|
||||
[ "Unicode support not available" throw ] or
|
||||
] change-at
|
||||
|
||||
: (parse-string) ( m str -- n )
|
||||
2dup nth CHAR: " =
|
||||
[ drop 1+ ] [ [ next-char , ] keep (parse-string) ] if ;
|
||||
: unicode-escape ( str -- ch str' )
|
||||
"{" ?head-slice [
|
||||
CHAR: } over index cut-slice
|
||||
>r >string name>char-hook get call r>
|
||||
1 tail-slice
|
||||
] [
|
||||
6 cut-slice >r hex> r>
|
||||
] if ;
|
||||
|
||||
: next-escape ( str -- ch str' )
|
||||
"u" ?head-slice [
|
||||
unicode-escape
|
||||
] [
|
||||
unclip-slice escape swap
|
||||
] if ;
|
||||
|
||||
: (parse-string) ( str -- m )
|
||||
dup [ "\"\\" member? ] find dup [
|
||||
>r cut-slice >r % r> 1 tail-slice r>
|
||||
dup CHAR: " = [
|
||||
drop slice-from
|
||||
] [
|
||||
drop next-escape >r , r> (parse-string)
|
||||
] if
|
||||
] [
|
||||
"Unterminated string" throw
|
||||
] if ;
|
||||
|
||||
: parse-string ( -- str )
|
||||
lexer get [
|
||||
[ (parse-string) ] "" make swap
|
||||
[ swap tail-slice (parse-string) ] "" make swap
|
||||
] change-column ;
|
||||
|
||||
TUPLE: parse-error file line col text ;
|
||||
|
|
|
@ -100,13 +100,9 @@ ARTICLE: "escape" "Character escape codes"
|
|||
{ { $snippet "\\0" } "a null byte (ASCII 0)" }
|
||||
{ { $snippet "\\e" } "escape (ASCII 27)" }
|
||||
{ { $snippet "\\\"" } { $snippet "\"" } }
|
||||
}
|
||||
"A Unicode character can be specified by its code number by writing " { $snippet "\\u" } " followed by a six-digit hexadecimal number. That is, the following two expressions are equivalent:"
|
||||
{ $code
|
||||
"CHAR: \\u000078"
|
||||
"78"
|
||||
}
|
||||
"While not useful for single characters, this syntax is also permitted inside strings." ;
|
||||
{ { $snippet "\\u" { $emphasis "xxxxxx" } } { "The Unicode code point with hexadecimal number " { $snippet { $emphasis "xxxxxx" } } } }
|
||||
{ { $snippet "\\u{" { $emphasis "name" } "}" } { "The Unicode code point named " { $snippet { $emphasis "name" } } } }
|
||||
} ;
|
||||
|
||||
ARTICLE: "syntax-strings" "Character and string syntax"
|
||||
"Factor has no distinct character type, however Unicode character value integers can be read by specifying a literal character, or an escaped representation thereof."
|
||||
|
@ -412,8 +408,17 @@ HELP: IN:
|
|||
|
||||
HELP: CHAR:
|
||||
{ $syntax "CHAR: token" }
|
||||
{ $values { "token" "a literal character or escape code" } }
|
||||
{ $description "Adds the Unicode code point of the character represented by the token to the parse tree." } ;
|
||||
{ $values { "token" "a literal character, escape code, or Unicode character name" } }
|
||||
{ $description "Adds a Unicode code point to the parse tree." }
|
||||
{ $examples
|
||||
{ $code
|
||||
"CHAR: x"
|
||||
"CHAR: \\u000032"
|
||||
"CHAR: \\u{exclamation-mark}"
|
||||
"CHAR: exclamation-mark"
|
||||
"CHAR: ugaritic-letter-samka"
|
||||
}
|
||||
} ;
|
||||
|
||||
HELP: "
|
||||
{ $syntax "\"string...\"" }
|
||||
|
|
|
@ -5,7 +5,8 @@ byte-vectors definitions generic hashtables kernel math
|
|||
namespaces parser sequences strings sbufs vectors words
|
||||
quotations io assocs splitting tuples generic.standard
|
||||
generic.math classes io.files vocabs float-arrays float-vectors
|
||||
classes.union classes.mixin classes.predicate compiler.units ;
|
||||
classes.union classes.mixin classes.predicate compiler.units
|
||||
combinators ;
|
||||
IN: bootstrap.syntax
|
||||
|
||||
! These words are defined as a top-level form, instead of with
|
||||
|
@ -56,7 +57,14 @@ IN: bootstrap.syntax
|
|||
"f" [ f parsed ] define-syntax
|
||||
"t" "syntax" lookup define-symbol
|
||||
|
||||
"CHAR:" [ 0 scan next-char nip parsed ] define-syntax
|
||||
"CHAR:" [
|
||||
scan {
|
||||
{ [ dup length 1 = ] [ first ] }
|
||||
{ [ "\\" ?head ] [ next-escape drop ] }
|
||||
{ [ t ] [ name>char-hook get call ] }
|
||||
} cond parsed
|
||||
] define-syntax
|
||||
|
||||
"\"" [ parse-string parsed ] define-syntax
|
||||
|
||||
"SBUF\"" [
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
! Copyright (C) 2007, 2008 Eduardo Cavazos, Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: namespaces splitting sequences io.files kernel assocs
|
||||
words vocabs definitions parser continuations inspector debugger
|
||||
io io.styles io.streams.lines hashtables sorting prettyprint
|
||||
source-files arrays combinators strings system math.parser
|
||||
compiler.errors ;
|
||||
USING: namespaces sequences io.files kernel assocs words vocabs
|
||||
definitions parser continuations inspector debugger io io.styles
|
||||
io.streams.lines hashtables sorting prettyprint source-files
|
||||
arrays combinators strings system math.parser compiler.errors
|
||||
splitting ;
|
||||
IN: vocabs.loader
|
||||
|
||||
SYMBOL: vocab-roots
|
||||
|
@ -16,7 +16,7 @@ V{
|
|||
} clone vocab-roots set-global
|
||||
|
||||
: vocab-dir ( vocab -- dir )
|
||||
vocab-name "." split "/" join ;
|
||||
vocab-name { { CHAR: . CHAR: / } } substitute ;
|
||||
|
||||
: vocab-dir+ ( vocab str/f -- path )
|
||||
>r vocab-name "." split r>
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
USING: vocabs.loader vocabs kernel ;
|
||||
|
||||
"bootstrap.help" vocab [ "help.handbook" require ] when
|
|
@ -14,8 +14,6 @@ IN: bootstrap.help
|
|||
[ vocab-root ] subset
|
||||
[ vocab-source-loaded? ] subset
|
||||
[ dup vocab-docs-loaded? [ drop ] [ load-docs ] if ] each
|
||||
] with-variable
|
||||
|
||||
"help.handbook" require ;
|
||||
] with-variable ;
|
||||
|
||||
load-help
|
||||
|
|
|
@ -4,10 +4,11 @@ USING: vocabs.loader sequences ;
|
|||
"bootstrap.image"
|
||||
"tools.annotations"
|
||||
"tools.crossref"
|
||||
! "tools.deploy"
|
||||
"tools.deploy"
|
||||
"tools.memory"
|
||||
"tools.profiler"
|
||||
"tools.test"
|
||||
"tools.time"
|
||||
"tools.disassembler"
|
||||
"editors"
|
||||
} [ require ] each
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
USING: help help.markup help.syntax help.topics
|
||||
namespaces words sequences classes assocs vocabs kernel
|
||||
arrays prettyprint.backend kernel.private io tools.browser
|
||||
generic math tools.profiler system ui strings sbufs vectors
|
||||
byte-arrays bit-arrays float-arrays quotations help.lint ;
|
||||
USING: help help.markup help.syntax help.definitions help.topics
|
||||
namespaces words sequences classes assocs vocabs kernel arrays
|
||||
prettyprint.backend kernel.private io generic math system
|
||||
strings sbufs vectors byte-arrays bit-arrays float-arrays
|
||||
quotations ;
|
||||
IN: help.handbook
|
||||
|
||||
ARTICLE: "conventions" "Conventions"
|
||||
|
@ -161,15 +161,20 @@ ARTICLE: "io" "Input and output"
|
|||
{ $subsection "io.timeouts" } ;
|
||||
|
||||
ARTICLE: "tools" "Developer tools"
|
||||
{ $subsection "tools.annotations" }
|
||||
{ $subsection "tools.crossref" }
|
||||
"Exploratory tools:"
|
||||
{ $subsection "editor" }
|
||||
{ $subsection "tools.crossref" }
|
||||
{ $subsection "inspector" }
|
||||
"Debugging tools:"
|
||||
{ $subsection "tools.annotations" }
|
||||
{ $subsection "tools.test" }
|
||||
{ $subsection "meta-interpreter" }
|
||||
"Performance tools:"
|
||||
{ $subsection "tools.memory" }
|
||||
{ $subsection "profiling" }
|
||||
{ $subsection "tools.test" }
|
||||
{ $subsection "timing" }
|
||||
{ $subsection "tools.disassembler" }
|
||||
"Deployment tools:"
|
||||
{ $subsection "tools.deploy" } ;
|
||||
|
||||
ARTICLE: "article-index" "Article index"
|
||||
|
@ -201,7 +206,6 @@ ARTICLE: "handbook" "Factor documentation"
|
|||
{ $subsection "cookbook" }
|
||||
{ $subsection "first-program" }
|
||||
{ $subsection "vocab-index" }
|
||||
{ $subsection "changes" }
|
||||
{ $heading "Language reference" }
|
||||
{ $subsection "conventions" }
|
||||
{ $subsection "syntax" }
|
||||
|
@ -231,137 +235,6 @@ ARTICLE: "handbook" "Factor documentation"
|
|||
{ $subsection "type-index" }
|
||||
{ $subsection "class-index" } ;
|
||||
|
||||
|
||||
USING: io.files io.sockets float-arrays inference ;
|
||||
|
||||
ARTICLE: "changes" "Changes in the latest release"
|
||||
{ $heading "Factor 0.91" }
|
||||
{ $subheading "Performance" }
|
||||
{ $list
|
||||
{ "Continuations are now supported by the static stack effect system. This means that the " { $link infer } " word and the optimizing compiler now both support code which uses continuations." }
|
||||
{ "Many words which previously ran in the interpreter, such as error handling and I/O, are now compiled to optimized machine code." }
|
||||
{ "A non-optimizing, just-in-time compiler replaces the interpreter with no loss in functionality or introspective ability." }
|
||||
{ "The non-optimizing compiler compiles quotations the first time they are called, generating a series of stack pushes and subroutine calls. It offers a 33%-50% performance increase over the interpreter." }
|
||||
{ "The optimizing compiler now performs some more representation inference. Alien pointers are unboxed where possible. This improves performance of the " { $vocab-link "ogg.player" } " Ogg Theora video player." }
|
||||
{ "The queue of sleeping tasks is now a sorted priority queue. This reduces overhead for workloads involving large numbers of sleeping threads (Doug Coleman)" }
|
||||
{ "Improved hash code algorithm for sequences" }
|
||||
{ "New, efficient implementations of " { $link bit? } " and " { $link log2 } " runs in constant time for large bignums" }
|
||||
{ "New " { $link big-random } " word for generating large random numbers quickly" }
|
||||
{ "Improved profiler no longer has to be explicitly enabled and disabled with a full recompile; instead, the " { $link profile } " word can be used at any time, and it dynamically patches words to increment call counts. There is no overhead when the profiler is not in use." }
|
||||
{ "Calls to " { $link member? } " with a literal sequence are now open-coded. If there are four or fewer elements, a series of conditionals are generated; if there are more than four elements, there is a hash dispatch followed by conditionals in each branch." }
|
||||
}
|
||||
{ $subheading "IO" }
|
||||
{ $list
|
||||
{ "More robust Windows CE native I/O" }
|
||||
{ "New " { $link os-envs } " word to get the current set of environment variables" }
|
||||
{ "Redesigned " { $vocab-link "io.launcher" } " supports passing environment variables to the child process" }
|
||||
{ { $link <process-stream> } " implemented on Windows (Doug Coleman)" }
|
||||
{ "Updated " { $vocab-link "io.mmap" } " for new module system, now supports Windows CE (Doug Coleman)" }
|
||||
{ { $vocab-link "io.sniffer" } " - packet sniffer library (Doug Coleman, Elie Chaftari)" }
|
||||
{ { $vocab-link "io.server" } " - improved logging support, logs to a file by default" }
|
||||
{ { $vocab-link "io.files" } " - several new file system manipulation words added" }
|
||||
{ { $vocab-link "tar" } " - tar file extraction in pure Factor (Doug Coleman)" }
|
||||
{ { $vocab-link "unix.linux" } ", " { $vocab-link "raptor" } " - ``Raptor Linux'', a set of alien bindings to low-level Linux features, such as network interface configuration, file system mounting/unmounting, etc, together with experimental boot scripts intended to entirely replace " { $snippet "/sbin/init" } ", " { $snippet "/etc/inittab" } " and " { $snippet "/etc/init.d/" } " (Eduardo Cavazos)." }
|
||||
}
|
||||
{ $subheading "Tools" }
|
||||
{ $list
|
||||
{ "Graphical deploy tool added - see " { $link "ui.tools.deploy" } }
|
||||
{ "The deploy tool now supports Windows" }
|
||||
{ { $vocab-link "network-clipboard" } " - clipboard synchronization with a simple TCP/IP protocol" }
|
||||
}
|
||||
{ $subheading "UI" }
|
||||
{ $list
|
||||
{ { $vocab-link "cairo" } " - updated for new module system, new features (Sampo Vuori)" }
|
||||
{ { $vocab-link "springies" } " - physics simulation UI demo (Eduardo Cavazos)" }
|
||||
{ { $vocab-link "ui.gadgets.buttons" } " - added check box and radio button gadgets" }
|
||||
{ "Double- and triple-click-drag now supported in the editor gadget to select words or lines at a time" }
|
||||
{ "Windows can be closed on request now using " { $link close-window } }
|
||||
{ "New icons (Elie Chaftari)" }
|
||||
}
|
||||
{ $subheading "Libraries" }
|
||||
{ $list
|
||||
{ "The " { $snippet "queues" } " vocabulary has been removed because its functionality is a subset of " { $vocab-link "dlists" } }
|
||||
{ "The " { $vocab-link "webapps.cgi" } " vocabulary implements CGI support for the Factor HTTP server." }
|
||||
{ "The optimizing compiler no longer depends on the number tower and it is possible to bootstrap a minimal image by just passing " { $snippet "-include=compiler" } " to stage 2 bootstrap." }
|
||||
{ { $vocab-link "benchmark.knucleotide" } " - new benchmark (Eric Mertens)" }
|
||||
{ { $vocab-link "channels" } " - concurrent message passing over message channels" }
|
||||
{ { $vocab-link "destructors" } " - deterministic scope-based resource deallocation (Doug Coleman)" }
|
||||
{ { $vocab-link "dlists" } " - various updates (Doug Coleman)" }
|
||||
{ { $vocab-link "editors.emeditor" } " - EmEditor integration (Doug Coleman)" }
|
||||
{ { $vocab-link "editors.editplus" } " - EditPlus integration (Aaron Schaefer)" }
|
||||
{ { $vocab-link "editors.notepadpp" } " - Notepad++ integration (Doug Coleman)" }
|
||||
{ { $vocab-link "editors.ted-notepad" } " - TED Notepad integration (Doug Coleman)" }
|
||||
{ { $vocab-link "editors.ultraedit" } " - UltraEdit integration (Doug Coleman)" }
|
||||
{ { $vocab-link "globs" } " - simple Unix shell-style glob patterns" }
|
||||
{ { $vocab-link "heaps" } " - updated for new module system and cleaned up (Doug Coleman)" }
|
||||
{ { $vocab-link "peg" } " - Parser Expression Grammars, a new appoach to parser construction, similar to parser combinators (Chris Double)" }
|
||||
{ { $vocab-link "regexp" } " - revived from " { $snippet "unmaintained/" } " and completely redesigned (Doug Coleman)" }
|
||||
{ { $vocab-link "rss" } " - add Atom feed generation (Daniel Ehrenberg)" }
|
||||
{ { $vocab-link "tuples.lib" } " - some utility words for working with tuples (Doug Coleman)" }
|
||||
{ { $vocab-link "webapps.pastebin" } " - improved appearance, add Atom feed generation, add syntax highlighting using " { $vocab-link "xmode" } }
|
||||
{ { $vocab-link "webapps.planet" } " - add Atom feed generation" }
|
||||
}
|
||||
{ $heading "Factor 0.90" }
|
||||
{ $subheading "Core" }
|
||||
{ $list
|
||||
{ "New module system; see " { $link "vocabs.loader" } ". (Eduardo Cavazos)" }
|
||||
{ "Tuple constructors are defined differently now; see " { $link "tuple-constructors" } "." }
|
||||
{ "Mixin classes implemented; these are essentially extensible unions. See " { $link "mixins" } "." }
|
||||
{ "New " { $link float-array } " data type implements a space-efficient sequence of floats." }
|
||||
{ "Moved " { $link <file-appender> } ", " { $link delete-file } ", " { $link make-directory } ", " { $link delete-directory } " words from " { $snippet "libs/io" } " into the core, and fixed them to work on more platforms." }
|
||||
{ "New " { $link host-name } " word." }
|
||||
{ "The " { $link directory } " word now outputs an array of pairs, with the second element of each pair indicating if that entry is a subdirectory. This saves an unnecessary " { $link stat } " call when traversing directory hierarchies, which speeds things up." }
|
||||
{ "IPv6 is now supported, along with Unix domain sockets (the latter on Unix systems only). The stack effects of " { $link <client> } " and " { $link <server> } " have changed, since they now take generic address specifiers; see " { $link "network-streams" } "." }
|
||||
{ "The stage 2 bootstrap process is more flexible, and various subsystems such as help, tools and the UI can be omitted by supplying command line switches; see " { $link "bootstrap-cli-args" } "." }
|
||||
{ "The " { $snippet "-shell" } " command line switch has been replaced by a " { $snippet "-run" } " command line switch; see " { $link "standard-cli-args" } "." }
|
||||
{ "Variable usage inference has been removed; the " { $link infer } " word no longer reports this information." }
|
||||
|
||||
}
|
||||
{ $subheading "Tools" }
|
||||
{ $list
|
||||
{ "Stand-alone image deployment; see " { $link "tools.deploy" } "." }
|
||||
{ "Stand-alone application bundle deployment on Mac OS X; see " { $vocab-link "tools.deploy.app" } "." }
|
||||
{ "New vocabulary browser tool in the UI." }
|
||||
{ "New profiler tool in the UI." }
|
||||
}
|
||||
{ $subheading "Extras" }
|
||||
"Most existing libraries were improved when ported to the new module system; the most notable changes include:"
|
||||
{ $list
|
||||
{ { $vocab-link "asn1" } ": ASN1 parser and writer. (Elie Chaftari)" }
|
||||
{ { $vocab-link "benchmark" } ": new set of benchmarks." }
|
||||
{ { $vocab-link "cfdg" } ": Context-free design grammar implementation; see " { $url "http://www.chriscoyne.com/cfdg/" } ". (Eduardo Cavazos)" }
|
||||
{ { $vocab-link "cryptlib" } ": Cryptlib library binding. (Elie Chaftari)" }
|
||||
{ { $vocab-link "cryptlib.streams" } ": Streams which perform SSL encryption and decryption. (Matthew Willis)" }
|
||||
{ { $vocab-link "hints" } ": Give type specialization hints to the compiler." }
|
||||
{ { $vocab-link "inverse" } ": Invertible computation and concatenative pattern matching. (Daniel Ehrenberg)" }
|
||||
{ { $vocab-link "ldap" } ": OpenLDAP library binding. (Elie Chaftari)" }
|
||||
{ { $vocab-link "locals" } ": Efficient lexically scoped locals, closures, and local words." }
|
||||
{ { $vocab-link "mortar" } ": Experimental message-passing object system. (Eduardo Cavazos)" }
|
||||
{ { $vocab-link "openssl" } ": OpenSSL library binding. (Elie Chaftari)" }
|
||||
{ { $vocab-link "pack" } ": Utility for reading and writing binary data. (Doug Coleman)" }
|
||||
{ { $vocab-link "pdf" } ": Haru PDF library binding. (Elie Chaftari)" }
|
||||
{ { $vocab-link "qualified" } ": Refer to words from another vocabulary without adding the entire vocabulary to the search path. (Daniel Ehrenberg)" }
|
||||
{ { $vocab-link "roman" } ": Reading and writing Roman numerals. (Doug Coleman)" }
|
||||
{ { $vocab-link "scite" } ": SciTE editor integration. (Clemens Hofreither)" }
|
||||
{ { $vocab-link "smtp" } ": SMTP client with support for CRAM-MD5 authentication. (Elie Chaftari, Dirk Vleugels)" }
|
||||
{ { $vocab-link "tuple-arrays" } ": Space-efficient packed tuple arrays. (Daniel Ehrenberg)" }
|
||||
{ { $vocab-link "unicode" } ": major new functionality added. (Daniel Ehrenberg)" }
|
||||
}
|
||||
{ $subheading "Performance" }
|
||||
{ $list
|
||||
{ "The " { $link curry } " word now runs in constant time, and curried quotations can be called from compiled code; this allows for abstractions and idioms which were previously impractical due to performance issues. In particular, words such as " { $snippet "each-with" } " and " { $snippet "map-with" } " are gone; " { $snippet "each-with" } " can now be written as " { $snippet "with each" } ", and similarly for other " { $snippet "-with" } " combinators." }
|
||||
"Improved generational promotion strategy in garbage collector reduces the amount of junk which makes its way into tenured space, which in turn reduces the frequency of full garbage collections."
|
||||
"Faster generic word dispatch and union membership testing."
|
||||
{ "Alien memory accessors (" { $link "reading-writing-memory" } ") are compiled as intrinsics where possible, which improves performance in code which iteroperates with C libraries." }
|
||||
}
|
||||
{ $subheading "Platforms" }
|
||||
{ $list
|
||||
"Networking support added for Windows CE. (Doug Coleman)"
|
||||
"UDP/IP networking support added for all Windows platforms. (Doug Coleman)"
|
||||
"Solaris/x86 fixes. (Samuel Tardieu)"
|
||||
"Linux/AMD64 port works again."
|
||||
} ;
|
||||
|
||||
{ <array> <string> <sbuf> <vector> <byte-array> <bit-array> <float-array> }
|
||||
related-words
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ USING: continuations destructors io.buffers io.files io.backend
|
|||
io.timeouts io.nonblocking io.windows io.windows.nt.backend
|
||||
kernel libc math threads windows windows.kernel32 alien.c-types
|
||||
alien.arrays sequences combinators combinators.lib sequences.lib
|
||||
ascii splitting alien strings ;
|
||||
ascii splitting alien strings assocs ;
|
||||
IN: io.windows.nt.files
|
||||
|
||||
M: windows-nt-io cwd
|
||||
|
@ -60,7 +60,7 @@ M: windows-nt-io root-directory? ( path -- ? )
|
|||
|
||||
M: windows-nt-io normalize-pathname ( string -- string )
|
||||
dup string? [ "pathname must be a string" throw ] unless
|
||||
"/" split "\\" join
|
||||
{ { CHAR: / CHAR: \\ } } substitute
|
||||
cwd swap windows-path+
|
||||
[ "/\\." member? ] right-trim
|
||||
dup peek CHAR: : = [ "\\" append ] when ;
|
||||
|
|
|
@ -9,13 +9,10 @@ quotations promises combinators io ;
|
|||
IN: lazy-lists
|
||||
|
||||
! Lazy List Protocol
|
||||
MIXIN: list
|
||||
GENERIC: car ( cons -- car )
|
||||
GENERIC: cdr ( cons -- cdr )
|
||||
GENERIC: nil? ( cons -- ? )
|
||||
GENERIC: list? ( object -- ? )
|
||||
|
||||
M: object list? ( object -- bool )
|
||||
drop f ;
|
||||
|
||||
M: promise car ( promise -- car )
|
||||
force car ;
|
||||
|
@ -26,9 +23,6 @@ M: promise cdr ( promise -- cdr )
|
|||
M: promise nil? ( cons -- bool )
|
||||
force nil? ;
|
||||
|
||||
M: promise list? ( object -- bool )
|
||||
drop t ;
|
||||
|
||||
TUPLE: cons car cdr ;
|
||||
|
||||
C: cons cons
|
||||
|
@ -45,9 +39,6 @@ M: cons cdr ( cons -- cdr )
|
|||
M: cons nil? ( cons -- bool )
|
||||
nil eq? ;
|
||||
|
||||
M: cons list? ( object -- bool )
|
||||
drop t ;
|
||||
|
||||
: 1list ( obj -- cons )
|
||||
nil cons ;
|
||||
|
||||
|
@ -74,9 +65,6 @@ M: lazy-cons cdr ( lazy-cons -- cdr )
|
|||
M: lazy-cons nil? ( lazy-cons -- bool )
|
||||
nil eq? ;
|
||||
|
||||
M: lazy-cons list? ( object -- bool )
|
||||
drop t ;
|
||||
|
||||
: 1lazy-list ( a -- lazy-cons )
|
||||
[ nil ] lazy-cons ;
|
||||
|
||||
|
@ -138,9 +126,6 @@ M: memoized-cons nil? ( memoized-cons -- bool )
|
|||
memoized-cons-nil?
|
||||
] if ;
|
||||
|
||||
M: memoized-cons list? ( object -- bool )
|
||||
drop t ;
|
||||
|
||||
TUPLE: lazy-map cons quot ;
|
||||
|
||||
C: <lazy-map> lazy-map
|
||||
|
@ -159,9 +144,6 @@ M: lazy-map cdr ( lazy-map -- cdr )
|
|||
M: lazy-map nil? ( lazy-map -- bool )
|
||||
lazy-map-cons nil? ;
|
||||
|
||||
M: lazy-map list? ( object -- bool )
|
||||
drop t ;
|
||||
|
||||
TUPLE: lazy-map-with value cons quot ;
|
||||
|
||||
C: <lazy-map-with> lazy-map-with
|
||||
|
@ -182,9 +164,6 @@ M: lazy-map-with cdr ( lazy-map-with -- cdr )
|
|||
M: lazy-map-with nil? ( lazy-map-with -- bool )
|
||||
lazy-map-with-cons nil? ;
|
||||
|
||||
M: lazy-map-with list? ( object -- bool )
|
||||
drop t ;
|
||||
|
||||
TUPLE: lazy-take n cons ;
|
||||
|
||||
C: <lazy-take> lazy-take
|
||||
|
@ -206,9 +185,6 @@ M: lazy-take nil? ( lazy-take -- bool )
|
|||
lazy-take-cons nil?
|
||||
] if ;
|
||||
|
||||
M: lazy-take list? ( object -- bool )
|
||||
drop t ;
|
||||
|
||||
TUPLE: lazy-until cons quot ;
|
||||
|
||||
C: <lazy-until> lazy-until
|
||||
|
@ -226,9 +202,6 @@ M: lazy-until cdr ( lazy-until -- cdr )
|
|||
M: lazy-until nil? ( lazy-until -- bool )
|
||||
drop f ;
|
||||
|
||||
M: lazy-until list? ( lazy-until -- bool )
|
||||
drop t ;
|
||||
|
||||
TUPLE: lazy-while cons quot ;
|
||||
|
||||
C: <lazy-while> lazy-while
|
||||
|
@ -245,9 +218,6 @@ M: lazy-while cdr ( lazy-while -- cdr )
|
|||
M: lazy-while nil? ( lazy-while -- bool )
|
||||
[ car ] keep lazy-while-quot call not ;
|
||||
|
||||
M: lazy-while list? ( lazy-while -- bool )
|
||||
drop t ;
|
||||
|
||||
TUPLE: lazy-subset cons quot ;
|
||||
|
||||
C: <lazy-subset> lazy-subset
|
||||
|
@ -285,9 +255,6 @@ M: lazy-subset nil? ( lazy-subset -- bool )
|
|||
] if
|
||||
] if ;
|
||||
|
||||
M: lazy-subset list? ( object -- bool )
|
||||
drop t ;
|
||||
|
||||
: list>vector ( list -- vector )
|
||||
[ [ , ] leach ] V{ } make ;
|
||||
|
||||
|
@ -311,9 +278,6 @@ M: lazy-append cdr ( lazy-append -- cdr )
|
|||
M: lazy-append nil? ( lazy-append -- bool )
|
||||
drop f ;
|
||||
|
||||
M: lazy-append list? ( object -- bool )
|
||||
drop t ;
|
||||
|
||||
TUPLE: lazy-from-by n quot ;
|
||||
|
||||
C: lfrom-by lazy-from-by ( n quot -- list )
|
||||
|
@ -331,9 +295,6 @@ M: lazy-from-by cdr ( lazy-from-by -- cdr )
|
|||
M: lazy-from-by nil? ( lazy-from-by -- bool )
|
||||
drop f ;
|
||||
|
||||
M: lazy-from-by list? ( object -- bool )
|
||||
drop t ;
|
||||
|
||||
TUPLE: lazy-zip list1 list2 ;
|
||||
|
||||
C: <lazy-zip> lazy-zip
|
||||
|
@ -351,9 +312,6 @@ M: lazy-zip cdr ( lazy-zip -- cdr )
|
|||
M: lazy-zip nil? ( lazy-zip -- bool )
|
||||
drop f ;
|
||||
|
||||
M: lazy-zip list? ( object -- bool )
|
||||
drop t ;
|
||||
|
||||
TUPLE: sequence-cons index seq ;
|
||||
|
||||
C: <sequence-cons> sequence-cons
|
||||
|
@ -376,9 +334,6 @@ M: sequence-cons cdr ( sequence-cons -- cdr )
|
|||
M: sequence-cons nil? ( sequence-cons -- bool )
|
||||
drop f ;
|
||||
|
||||
M: sequence-cons list? ( object -- bool )
|
||||
drop t ;
|
||||
|
||||
: >list ( object -- list )
|
||||
{
|
||||
{ [ dup sequence? ] [ 0 swap seq>list ] }
|
||||
|
@ -419,9 +374,6 @@ M: lazy-concat nil? ( lazy-concat -- bool )
|
|||
drop f
|
||||
] if ;
|
||||
|
||||
M: lazy-concat list? ( object -- bool )
|
||||
drop t ;
|
||||
|
||||
: lcartesian-product ( list1 list2 -- result )
|
||||
swap [ swap [ 2array ] lmap-with ] lmap-with lconcat ;
|
||||
|
||||
|
@ -492,3 +444,20 @@ M: lazy-io cdr ( lazy-io -- cdr )
|
|||
|
||||
M: lazy-io nil? ( lazy-io -- bool )
|
||||
car not ;
|
||||
|
||||
INSTANCE: cons list
|
||||
INSTANCE: sequence-cons list
|
||||
INSTANCE: memoized-cons list
|
||||
INSTANCE: promise list
|
||||
INSTANCE: lazy-io list
|
||||
INSTANCE: lazy-concat list
|
||||
INSTANCE: lazy-cons list
|
||||
INSTANCE: lazy-map list
|
||||
INSTANCE: lazy-map-with list
|
||||
INSTANCE: lazy-take list
|
||||
INSTANCE: lazy-append list
|
||||
INSTANCE: lazy-from-by list
|
||||
INSTANCE: lazy-zip list
|
||||
INSTANCE: lazy-while list
|
||||
INSTANCE: lazy-until list
|
||||
INSTANCE: lazy-subset list
|
||||
|
|
|
@ -4,7 +4,7 @@ USING: classes inference inference.dataflow io kernel
|
|||
kernel.private math.parser namespaces optimizer prettyprint
|
||||
prettyprint.backend sequences words arrays match macros
|
||||
assocs sequences.private optimizer.specializers generic
|
||||
combinators sorting math ;
|
||||
combinators sorting math quotations ;
|
||||
IN: optimizer.debugger
|
||||
|
||||
! A simple tool for turning dataflow IR into quotations, for
|
||||
|
@ -67,7 +67,7 @@ M: #shuffle node>quot
|
|||
[ , ] [ >r drop t r> ] if*
|
||||
dup effect-str "#shuffle: " swap append comment, ;
|
||||
|
||||
: pushed-literals node-out-d [ value-literal ] map ;
|
||||
: pushed-literals node-out-d [ value-literal literalize ] map ;
|
||||
|
||||
M: #push node>quot nip pushed-literals % ;
|
||||
|
||||
|
@ -83,6 +83,7 @@ M: #call-label node>quot #call>quot ;
|
|||
|
||||
M: #label node>quot
|
||||
[
|
||||
dup node-param literalize ,
|
||||
dup #label-loop? "#loop: " "#label: " ?
|
||||
over node-param word-name append comment,
|
||||
] 2keep
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
IN: optimizer.report
|
||||
USING: assocs words sequences arrays compiler tools.time
|
||||
io.styles io prettyprint vocabs kernel sorting generator
|
||||
optimizer ;
|
||||
|
||||
: count-optimization-passes ( nodes n -- n )
|
||||
>r optimize-1
|
||||
[ r> 1+ count-optimization-passes ] [ drop r> ] if ;
|
||||
|
||||
: word-table
|
||||
[ [ second ] swap compose compare ] curry sort 20 tail*
|
||||
print
|
||||
standard-table-style
|
||||
[
|
||||
[ [ [ pprint-cell ] each ] with-row ] each
|
||||
] tabular-output ;
|
||||
|
||||
: optimizer-report
|
||||
all-words [ compiled? ] subset
|
||||
[
|
||||
dup [
|
||||
word-dataflow nip 1 count-optimization-passes
|
||||
] benchmark nip 2array
|
||||
] { } map>assoc
|
||||
[ first ] "Worst number of optimizer passes:" results
|
||||
[ second ] "Worst compile times:" results ;
|
||||
|
||||
MAIN: optimizer-report
|
|
@ -205,6 +205,3 @@ PRIVATE>
|
|||
|
||||
: attempt-each ( seq quot -- result )
|
||||
(each) iterate-prep (attempt-each-integer) ; inline
|
||||
|
||||
: replace ( seq old new -- newseq )
|
||||
[ pick pick = [ 2nip ] [ 2drop ] if ] 2curry map ;
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
IN: tools.disassembler
|
||||
USING: help.markup help.syntax sequences.private ;
|
||||
|
||||
HELP: disassemble
|
||||
{ $values { "obj" "a word or a pair of addresses" } }
|
||||
{ $description "Disassembles either a compiled word definition or an arbitrary memory range (in the case " { $snippet "obj" } " is a pair of integers) by attaching " { $snippet "gdb" } " to the Factor VM and capturing the output." }
|
||||
{ $notes "In some cases the Factor compiler emits data inline with code, which can confuse " { $snippet "gdb" } ". This occurs in words which call " { $link dispatch } ", where the jump table addresses are compiled inline. Also on the ARM architecture, various pointers are often compiled inline, and the preceeding instruction jumps over the inline pinter." } ;
|
||||
|
||||
ARTICLE: "tools.disassembler" "Disassembling words"
|
||||
"The " { $vocab-link "tools.disassembler" } " vocabulary integrates Factor with the GNU debugger (" { $snippet "gdb" } ") for viewing the assembly code generated by the compiler. It can be used on both Unix and Windows as long as a working copy of " { $snippet "gdb" } " is installed and available in the " { $snippet "PATH" } "."
|
||||
{ $subsection disassemble } ;
|
||||
|
||||
ABOUT: "tools.disassembler"
|
|
@ -2,7 +2,7 @@
|
|||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: io.files io words alien kernel math.parser alien.syntax
|
||||
io.launcher system assocs arrays sequences namespaces qualified
|
||||
regexp system math sequences.lib windows.kernel32 ;
|
||||
system math windows.kernel32 generator.fixup ;
|
||||
IN: tools.disassembler
|
||||
|
||||
: in-file "gdb-in.txt" resource-path ;
|
||||
|
@ -12,7 +12,7 @@ IN: tools.disassembler
|
|||
GENERIC: make-disassemble-cmd ( obj -- )
|
||||
|
||||
M: word make-disassemble-cmd
|
||||
word-xt cell - 2array make-disassemble-cmd ;
|
||||
word-xt code-format - 2array make-disassemble-cmd ;
|
||||
|
||||
M: pair make-disassemble-cmd
|
||||
in-file [
|
||||
|
@ -30,12 +30,9 @@ M: pair make-disassemble-cmd
|
|||
] { } make-assoc run-process drop
|
||||
out-file file-lines ;
|
||||
|
||||
: relevant? ( line -- ? )
|
||||
R/ 0x.*:.*/ matches? ;
|
||||
|
||||
: tabs>spaces ( str -- str' )
|
||||
CHAR: \t CHAR: \s replace ;
|
||||
{ { CHAR: \t CHAR: \s } } substitute ;
|
||||
|
||||
: disassemble ( word -- )
|
||||
make-disassemble-cmd run-gdb
|
||||
[ relevant? ] subset [ tabs>spaces ] map [ print ] each ;
|
||||
[ tabs>spaces ] map [ print ] each ;
|
||||
|
|
|
@ -17,7 +17,7 @@ ARTICLE: "tools.memory" "Object memory tools"
|
|||
"The garbage collector can be invoked manually:"
|
||||
{ $subsection data-gc }
|
||||
{ $subsection code-gc }
|
||||
{ $see-also "image" } ;
|
||||
{ $see-also "images" } ;
|
||||
|
||||
ABOUT: "tools.memory"
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ GENERIC: command-word ( command -- word )
|
|||
update-gestures ;
|
||||
|
||||
: (command-name) ( string -- newstring )
|
||||
"-" split " " join >title ;
|
||||
{ { CHAR: - CHAR: \s } } substitute >title ;
|
||||
|
||||
M: word command-name ( word -- str )
|
||||
word-name
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
USING: assocs math kernel sequences sequences.lib io.files
|
||||
hashtables quotations splitting arrays math.parser
|
||||
combinators.lib hash2 byte-arrays words namespaces words
|
||||
compiler.units parser ;
|
||||
USING: assocs math kernel sequences io.files hashtables
|
||||
quotations splitting arrays math.parser combinators.lib hash2
|
||||
byte-arrays words namespaces words compiler.units parser ;
|
||||
IN: unicode.data
|
||||
|
||||
<<
|
||||
|
@ -68,7 +67,7 @@ IN: unicode.data
|
|||
: process-combining ( data -- hash )
|
||||
3 swap (process-data)
|
||||
[ string>number ] assoc-map
|
||||
[ nip 0 = not ] assoc-subset
|
||||
[ nip zero? not ] assoc-subset
|
||||
>hashtable ;
|
||||
|
||||
: categories ( -- names )
|
||||
|
@ -95,9 +94,9 @@ IN: unicode.data
|
|||
[ dup CHAR: A CHAR: Z between? [ HEX: 20 + ] when ] map ;
|
||||
|
||||
: process-names ( data -- names-hash )
|
||||
1 swap (process-data)
|
||||
[ ascii-lower CHAR: \s CHAR: - replace swap ] assoc-map
|
||||
>hashtable ;
|
||||
1 swap (process-data) [
|
||||
ascii-lower { { CHAR: \s CHAR: - } } substitute swap
|
||||
] assoc-map >hashtable ;
|
||||
|
||||
: multihex ( hexstring -- string )
|
||||
" " split [ hex> ] map [ ] subset ;
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
USING: unicode.syntax tools.test ;
|
||||
|
||||
[ CHAR: ! ] [ UNICHAR: exclamation-mark ] unit-test
|
||||
! Write a test for CATEGORY and CATEGORY-NOT
|
|
@ -46,7 +46,3 @@ IN: unicode.syntax
|
|||
: CATEGORY-NOT:
|
||||
CREATE ";" parse-tokens
|
||||
categories swap seq-minus define-category ; parsing
|
||||
|
||||
: UNICHAR:
|
||||
! This should be part of CHAR:. Also, name-map at ==> name>char
|
||||
scan name>char [ parsed ] [ "Invalid character" throw ] if* ; parsing
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
USING: unicode.syntax unicode.data unicode.breaks unicode.normalize
|
||||
unicode.case unicode.categories ;
|
||||
USING: unicode.syntax unicode.data unicode.breaks
|
||||
unicode.normalize unicode.case unicode.categories
|
||||
parser kernel namespaces ;
|
||||
IN: unicode
|
||||
|
||||
! For now: convenience to load all Unicode vocabs
|
||||
|
||||
[ name>char [ "Invalid character" throw ] unless* ]
|
||||
name>char-hook set-global
|
||||
|
|
Loading…
Reference in New Issue