Update documentation for stricter vocabulary search path semantics

db4
Slava Pestov 2009-05-16 00:29:21 -05:00
parent 79f5c30a7a
commit 66a9416473
63 changed files with 307 additions and 307 deletions

View File

@ -30,8 +30,8 @@ ARTICLE: "checksums.openssl" "OpenSSL checksums"
"An error thrown if the digest name is unrecognized:" "An error thrown if the digest name is unrecognized:"
{ $subsection unknown-digest } { $subsection unknown-digest }
"An example where we compute the SHA1 checksum of a string using the OpenSSL implementation of SHA1:" "An example where we compute the SHA1 checksum of a string using the OpenSSL implementation of SHA1:"
{ $example "USING: byte-arrays checksums checksums.openssl prettyprint ;" "\"hello world\" >byte-array openssl-sha1 checksum-bytes hex-string ." "\"2aae6c35c94fcfb415dbe95f408b9ce91ee846ed\"" } { $example "USING: byte-arrays checksums checksums.openssl ;" "\"hello world\" >byte-array openssl-sha1 checksum-bytes hex-string ." "\"2aae6c35c94fcfb415dbe95f408b9ce91ee846ed\"" }
"If we use the Factor implementation, we get the same result, just slightly slower:" "If we use the Factor implementation, we get the same result, just slightly slower:"
{ $example "USING: byte-arrays checksums checksums.sha1 prettyprint ;" "\"hello world\" >byte-array sha1 checksum-bytes hex-string ." "\"2aae6c35c94fcfb415dbe95f408b9ce91ee846ed\"" } ; { $example "USING: byte-arrays checksums checksums.sha1 ;" "\"hello world\" >byte-array sha1 checksum-bytes hex-string ." "\"2aae6c35c94fcfb415dbe95f408b9ce91ee846ed\"" } ;
ABOUT: "checksums.openssl" ABOUT: "checksums.openssl"

View File

@ -1,9 +1,8 @@
USING: alien alien.c-types alien.syntax compiler kernel USING: alien alien.c-types alien.syntax compiler kernel namespaces
namespaces namespaces tools.test sequences stack-checker sequences stack-checker stack-checker.errors words arrays parser
stack-checker.errors words arrays parser quotations quotations continuations effects namespaces.private io
continuations effects namespaces.private io io.streams.string io.streams.string memory system threads tools.test math accessors
memory system threads tools.test math accessors combinators combinators specialized-arrays.float alien.libraries io.pathnames
specialized-arrays.float alien.libraries io.pathnames
io.backend ; io.backend ;
IN: compiler.tests.alien IN: compiler.tests.alien

View File

@ -1,9 +1,9 @@
USING: generalizations accessors arrays compiler kernel USING: generalizations accessors arrays compiler kernel kernel.private
kernel.private math hashtables.private math.private namespaces math hashtables.private math.private namespaces sequences tools.test
sequences sequences.private tools.test namespaces.private namespaces.private slots.private sequences.private byte-arrays alien
slots.private sequences.private byte-arrays alien
alien.accessors layouts words definitions compiler.units io alien.accessors layouts words definitions compiler.units io
combinators vectors grouping make ; combinators vectors grouping make ;
QUALIFIED: namespaces.private
IN: compiler.tests.codegen IN: compiler.tests.codegen
! Originally, this file did black box testing of templating ! Originally, this file did black box testing of templating
@ -48,7 +48,7 @@ unit-test
[ 3 ] [ 3 ]
[ [
global [ 3 \ foo set ] bind global [ 3 \ foo set ] bind
\ foo [ global >n get ndrop ] compile-call \ foo [ global >n get namespaces.private:ndrop ] compile-call
] unit-test ] unit-test
: blech ( x -- ) drop ; : blech ( x -- ) drop ;
@ -62,7 +62,7 @@ unit-test
[ 3 ] [ 3 ]
[ [
global [ 3 \ foo set ] bind global [ 3 \ foo set ] bind
\ foo [ global [ get ] swap >n call ndrop ] compile-call \ foo [ global [ get ] swap >n call namespaces.private:ndrop ] compile-call
] unit-test ] unit-test
[ 3 ] [ 3 ]

View File

@ -1,10 +1,10 @@
USING: accessors arrays compiler.units kernel kernel.private math USING: accessors arrays compiler.units kernel kernel.private math
math.constants math.private sequences strings tools.test words math.constants math.private sequences strings tools.test words
continuations sequences.private hashtables.private byte-arrays continuations sequences.private hashtables.private byte-arrays
strings.private system random layouts vectors system random layouts vectors
sbufs strings.private slots.private alien math.order sbufs strings.private slots.private alien math.order
alien.accessors alien.c-types alien.syntax alien.strings alien.accessors alien.c-types alien.syntax alien.strings
namespaces libc sequences.private io.encodings.ascii namespaces libc io.encodings.ascii
classes compiler ; classes compiler ;
IN: compiler.tests.intrinsics IN: compiler.tests.intrinsics

View File

@ -1,5 +1,5 @@
USING: accessors math math.intervals sequences classes.algebra USING: accessors math math.intervals sequences classes.algebra
math kernel tools.test compiler.tree.propagation.info arrays ; kernel tools.test compiler.tree.propagation.info arrays ;
IN: compiler.tree.propagation.info.tests IN: compiler.tree.propagation.info.tests
[ f ] [ 0.0 -0.0 eql? ] unit-test [ f ] [ 0.0 -0.0 eql? ] unit-test

View File

@ -1,5 +1,5 @@
IN: compiler.tree.tuple-unboxing.tests IN: compiler.tree.tuple-unboxing.tests
USING: tools.test compiler.tree.tuple-unboxing compiler.tree USING: tools.test compiler.tree
compiler.tree.builder compiler.tree.recursive compiler.tree.builder compiler.tree.recursive
compiler.tree.normalization compiler.tree.propagation compiler.tree.normalization compiler.tree.propagation
compiler.tree.cleanup compiler.tree.escape-analysis compiler.tree.cleanup compiler.tree.escape-analysis

View File

@ -3,6 +3,7 @@ USING: tools.test concurrency.distributed kernel io.files
io.files.temp io.directories arrays io.sockets system io.files.temp io.directories arrays io.sockets system
combinators threads math sequences concurrency.messaging combinators threads math sequences concurrency.messaging
continuations accessors prettyprint ; continuations accessors prettyprint ;
FROM: concurrency.messaging => receive send ;
: test-node ( -- addrspec ) : test-node ( -- addrspec )
{ {

View File

@ -1,7 +1,8 @@
IN: concurrency.exchangers.tests IN: concurrency.exchangers.tests
USING: sequences tools.test concurrency.exchangers USING: tools.test concurrency.exchangers
concurrency.count-downs concurrency.promises locals kernel concurrency.count-downs concurrency.promises locals kernel
threads ; threads ;
FROM: sequences => 3append ;
:: exchanger-test ( -- string ) :: exchanger-test ( -- string )
[let | [let |

View File

@ -53,7 +53,7 @@ ARTICLE: { "concurrency" "synchronous-sends" } "Synchronous sends"
{ $subsection reply-synchronous } { $subsection reply-synchronous }
"An example:" "An example:"
{ $example { $example
"USING: concurrency.messaging kernel prettyprint threads ;" "USING: concurrency.messaging threads ;"
"IN: scratchpad" "IN: scratchpad"
": pong-server ( -- )" ": pong-server ( -- )"
" receive [ \"pong\" ] dip reply-synchronous ;" " receive [ \"pong\" ] dip reply-synchronous ;"

View File

@ -1,6 +1,7 @@
IN: cpu.ppc.assembler.tests IN: cpu.ppc.assembler.tests
USING: cpu.ppc.assembler tools.test arrays kernel namespaces USING: cpu.ppc.assembler tools.test arrays kernel namespaces
make vocabs sequences ; make vocabs sequences ;
FROM: cpu.ppc.assembler => B ;
: test-assembler ( expected quot -- ) : test-assembler ( expected quot -- )
[ 1array ] [ [ B{ } make ] curry ] bi* unit-test ; [ 1array ] [ [ B{ } make ] curry ] bi* unit-test ;

View File

@ -1,11 +1,12 @@
! Copyright (C) 2008 Doug Coleman. ! Copyright (C) 2008 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: io.files io.files.temp kernel tools.test db db.tuples classes USING: io.files io.files.temp kernel tools.test db db.tuples classes
db.types continuations namespaces math math.ranges db.types continuations namespaces math
prettyprint calendar sequences db.sqlite math.intervals prettyprint calendar sequences db.sqlite math.intervals
db.postgresql accessors random math.bitwise system db.postgresql accessors random math.bitwise system
math.ranges strings urls fry db.tuples.private db.private math.ranges strings urls fry db.tuples.private db.private
db.tester ; db.tester ;
FROM: math.ranges => [a,b] ;
IN: db.tuples.tests IN: db.tuples.tests
TUPLE: person the-id the-name the-number the-real TUPLE: person the-id the-name the-number the-real

View File

@ -2,6 +2,7 @@ USING: calendar ftp.server io.encodings.ascii io.files
io.files.unique namespaces threads tools.test kernel io.files.unique namespaces threads tools.test kernel
io.servers.connection ftp.client accessors urls io.servers.connection ftp.client accessors urls
io.pathnames io.directories sequences fry ; io.pathnames io.directories sequences fry ;
FROM: ftp.client => ftp-get ;
IN: ftp.server.tests IN: ftp.server.tests
: test-file-contents ( -- string ) : test-file-contents ( -- string )

View File

@ -136,7 +136,7 @@ ARTICLE: "cookbook-variables" "Dynamic variables cookbook"
} ; } ;
ARTICLE: "cookbook-vocabs" "Vocabularies cookbook" ARTICLE: "cookbook-vocabs" "Vocabularies cookbook"
"Rather than being in one flat list, words belong to vocabularies; every word is contained in exactly one. When parsing a word name, the parser searches the " { $emphasis "vocabulary search path" } ". When working at the listener, a useful set of vocabularies is already available. In a source file, all used vocabularies must be imported." "Rather than being in one flat list, words belong to vocabularies; every word is contained in exactly one. When parsing a word name, the parser searches through vocabularies. When working at the listener, a useful set of vocabularies is already available. In a source file, all used vocabularies must be imported."
$nl $nl
"For example, a source file containing the following code will print a parse error if you try loading it:" "For example, a source file containing the following code will print a parse error if you try loading it:"
{ $code "\"Hello world\" print" } { $code "\"Hello world\" print" }
@ -161,7 +161,7 @@ $nl
"You would have to place the first definition after the two others for the parser to accept the file." "You would have to place the first definition after the two others for the parser to accept the file."
{ $references { $references
{ } { }
"vocabulary-search" "word-search"
"words" "words"
"parser" "parser"
} ; } ;
@ -286,7 +286,6 @@ ARTICLE: "cookbook-pitfalls" "Pitfalls to avoid"
{ $list { $list
"Factor only makes use of one native thread, and Factor threads are scheduled co-operatively. C library calls block the entire VM." "Factor only makes use of one native thread, and Factor threads are scheduled co-operatively. C library calls block the entire VM."
"Factor does not hide anything from the programmer, all internals are exposed. It is your responsibility to avoid writing fragile code which depends too much on implementation detail." "Factor does not hide anything from the programmer, all internals are exposed. It is your responsibility to avoid writing fragile code which depends too much on implementation detail."
{ "When a source file uses two vocabularies which define words with the same name, the order of the vocabularies in the " { $link POSTPONE: USE: } " or " { $link POSTPONE: USING: } " forms is important. The " { $link POSTPONE: QUALIFIED: } " word implements qualified naming, which can be used to resolve ambiguities." }
{ "If a literal object appears in a word definition, the object itself is pushed on the stack when the word executes, not a copy. If you intend to mutate this object, you must " { $link clone } " it first. See " { $link "syntax-literals" } "." } { "If a literal object appears in a word definition, the object itself is pushed on the stack when the word executes, not a copy. If you intend to mutate this object, you must " { $link clone } " it first. See " { $link "syntax-literals" } "." }
{ "For a discussion of potential issues surrounding the " { $link f } " object, see " { $link "booleans" } "." } { "For a discussion of potential issues surrounding the " { $link f } " object, see " { $link "booleans" } "." }
{ "Factor's object system is quite flexible. Careless usage of union, mixin and predicate classes can lead to similar problems to those caused by “multiple inheritance” in other languages. In particular, it is possible to have two classes such that they have a non-empty intersection and yet neither is a subclass of the other. If a generic word defines methods on two such classes, various disambiguation rules are applied to ensure method dispatch remains deterministic, however they may not be what you expect. See " { $link "method-order" } " for details." } { "Factor's object system is quite flexible. Careless usage of union, mixin and predicate classes can lead to similar problems to those caused by “multiple inheritance” in other languages. In particular, it is possible to have two classes such that they have a non-empty intersection and yet neither is a subclass of the other. If a generic word defines methods on two such classes, various disambiguation rules are applied to ensure method dispatch remains deterministic, however they may not be what you expect. See " { $link "method-order" } " for details." }

View File

@ -248,14 +248,14 @@ ARTICLE: "handbook-language-reference" "The language"
{ $subsection "namespaces-global" } { $subsection "namespaces-global" }
{ $subsection "values" } { $subsection "values" }
{ $heading "Abstractions" } { $heading "Abstractions" }
{ $subsection "errors" } { $subsection "fry" }
{ $subsection "objects" } { $subsection "objects" }
{ $subsection "errors" }
{ $subsection "destructors" } { $subsection "destructors" }
{ $subsection "continuations" }
{ $subsection "memoize" } { $subsection "memoize" }
{ $subsection "parsing-words" } { $subsection "parsing-words" }
{ $subsection "macros" } { $subsection "macros" }
{ $subsection "fry" } { $subsection "continuations" }
{ $heading "Program organization" } { $heading "Program organization" }
{ $subsection "vocabs.loader" } { $subsection "vocabs.loader" }
"Vocabularies tagged " { $link T{ vocab-tag { name "extensions" } } } " implement various additional language abstractions." ; "Vocabularies tagged " { $link T{ vocab-tag { name "extensions" } } } " implement various additional language abstractions." ;

View File

@ -38,7 +38,7 @@ $nl
$nl $nl
"Now we have changed the source file, we must reload it into Factor so that we can test the new definition. To do this, simply go to the Factor listener and press " { $command tool "common" refresh-all } ". This will find any previously-loaded source files which have changed on disk, and reload them." "Now we have changed the source file, we must reload it into Factor so that we can test the new definition. To do this, simply go to the Factor listener and press " { $command tool "common" refresh-all } ". This will find any previously-loaded source files which have changed on disk, and reload them."
$nl $nl
"When you do this, you will get an error about the " { $link dup } " word not being found. This is because this word is part of the " { $vocab-link "kernel" } " vocabulary, but this vocabulary is not part of the source file's " { $link "vocabulary-search" } ". You must explicitly list dependencies in source files. This allows Factor to automatically load required vocabularies and makes larger programs easier to maintain." "When you do this, you will get an error about the " { $link dup } " word not being found. This is because this word is part of the " { $vocab-link "kernel" } " vocabulary, but this vocabulary is not part of the source file's " { $link "word-search" } ". You must explicitly list dependencies in source files. This allows Factor to automatically load required vocabularies and makes larger programs easier to maintain."
$nl $nl
"To add the word to the search path, first convince yourself that this word is in the " { $vocab-link "kernel" } " vocabulary. Enter " { $snippet "dup" } " in the listener's input area, and press " { $operation com-browse } ". This will open the documentation browser tool, viewing the help for the " { $link dup } " word. One of the subheadings in the help article will mention the word's vocabulary." "To add the word to the search path, first convince yourself that this word is in the " { $vocab-link "kernel" } " vocabulary. Enter " { $snippet "dup" } " in the listener's input area, and press " { $operation com-browse } ". This will open the documentation browser tool, viewing the help for the " { $link dup } " word. One of the subheadings in the help article will mention the word's vocabulary."
$nl $nl

View File

@ -3,6 +3,7 @@ USING: tools.test kernel io.streams.string
io.streams.null accessors inspector html.streams io.streams.null accessors inspector html.streams
html.components html.forms namespaces html.components html.forms namespaces
xml.writer ; xml.writer ;
FROM: html.components => inspector ;
[ ] [ begin-form ] unit-test [ ] [ begin-form ] unit-test

View File

@ -1,6 +1,7 @@
IN: html.forms.tests IN: html.forms.tests
USING: kernel sequences tools.test assocs html.forms validators accessors USING: kernel sequences tools.test assocs html.forms validators accessors
namespaces ; namespaces ;
FROM: html.forms => values ;
: with-validation ( quot -- messages ) : with-validation ( quot -- messages )
[ [

View File

@ -1,6 +1,6 @@
USING: html.streams html.streams.private accessors io USING: html.streams html.streams.private accessors io
io.streams.string io.styles kernel namespaces tools.test io.streams.string io.styles kernel namespaces tools.test
xml.writer sbufs sequences inspector colors xml.writer sbufs sequences inspector colors xml.writer
classes.predicate prettyprint ; classes.predicate prettyprint ;
IN: html.streams.tests IN: html.streams.tests

View File

@ -1,7 +1,7 @@
USING: html.templates html.templates.chloe USING: html.templates html.templates.chloe
tools.test io.streams.string kernel sequences ascii boxes tools.test io.streams.string kernel sequences ascii boxes
namespaces xml html.components html.forms namespaces xml html.components html.forms
splitting unicode.categories furnace accessors splitting furnace accessors
html.templates.chloe.compiler ; html.templates.chloe.compiler ;
IN: html.templates.chloe.tests IN: html.templates.chloe.tests

View File

@ -173,10 +173,10 @@ Set-Cookie: oo="bar; a=b"; comment="your mom"; httponly=yes
] unit-test ] unit-test
! Live-fire exercise ! Live-fire exercise
USING: http.server http.server.static furnace.sessions furnace.alloy USING: http.server.static furnace.sessions furnace.alloy
furnace.actions furnace.auth furnace.auth.login furnace.db http.client furnace.actions furnace.auth furnace.auth.login furnace.db
io.servers.connection io.files io.files.temp io.directories io io.encodings.ascii io.servers.connection io.files io.files.temp io.directories io
accessors namespaces threads threads
http.server.responses http.server.redirection furnace.redirection http.server.responses http.server.redirection furnace.redirection
http.server.dispatchers db.tuples ; http.server.dispatchers db.tuples ;

View File

@ -1,4 +1,4 @@
USING: io.files.info io.pathnames io.encodings.utf8 io.files USING: io.files.info io.encodings.utf8 io.files
io.directories kernel io.pathnames accessors tools.test io.directories kernel io.pathnames accessors tools.test
sequences io.files.temp ; sequences io.files.temp ;
IN: io.files.info.tests IN: io.files.info.tests

View File

@ -15,8 +15,6 @@ SYNTAX: hello "Hi" print ;
] with-file-vocabs ] with-file-vocabs
[ [
"debugger" add-ambiguous-use
[ [ \ + 1 2 3 4 ] ] [ [ \ + 1 2 3 4 ] ]
[ [
[ [

View File

@ -1,4 +1,4 @@
USING: lists.lazy.examples lists.lazy tools.test ; USING: lists.lazy.examples lists.lazy lists tools.test ;
IN: lists.lazy.examples.tests IN: lists.lazy.examples.tests
[ { 1 3 5 7 } ] [ 4 odds ltake list>array ] unit-test [ { 1 3 5 7 } ] [ 4 odds ltake list>array ] unit-test

View File

@ -93,22 +93,12 @@ HELP: luntil
{ $values { "list" "a cons object" } { "quot" { $quotation "( X -- ? )" } } { "result" "resulting cons object" } } { $values { "list" "a cons object" } { "quot" { $quotation "( X -- ? )" } } { "result" "resulting cons object" } }
{ $description "Outputs a lazy list containing the first items in the list until after " { $snippet "quot" } " evaluates to t. No evaluation of the list elements occurs initially but a " { $link <lazy-while> } " object is returned with conforms to the list protocol. Calling " { $link car } ", " { $link cdr } " or " { $link nil? } " on this will evaluate elements as required." } ; { $description "Outputs a lazy list containing the first items in the list until after " { $snippet "quot" } " evaluates to t. No evaluation of the list elements occurs initially but a " { $link <lazy-while> } " object is returned with conforms to the list protocol. Calling " { $link car } ", " { $link cdr } " or " { $link nil? } " on this will evaluate elements as required." } ;
HELP: list>vector
{ $values { "list" "a cons object" } { "vector" "the list converted to a vector" } }
{ $description "Convert a list to a vector. If the list is a lazy infinite list then this will enter an infinite loop." }
{ $see-also list>array } ;
HELP: list>array
{ $values { "list" "a cons object" } { "array" "the list converted to an array" } }
{ $description "Convert a list to an array. If the list is a lazy infinite list then this will enter an infinite loop." }
{ $see-also list>vector } ;
HELP: lappend HELP: lappend
{ $values { "list1" "a cons object" } { "list2" "a cons object" } { "result" "a lazy list of list2 appended to list1" } } { $values { "list1" "a cons object" } { "list2" "a cons object" } { "result" "a lazy list of list2 appended to list1" } }
{ $description "Perform a similar functionality to that of the " { $link append } " word, but in a lazy manner. No evaluation of the list elements occurs initially but a " { $link <lazy-append> } " object is returned which conforms to the list protocol. Calling " { $link car } ", " { $link cdr } " or " { $link nil? } " on this will evaluate elements as required. Successive calls to " { $link cdr } " will iterate through list1, followed by list2." } ; { $description "Perform a similar functionality to that of the " { $link append } " word, but in a lazy manner. No evaluation of the list elements occurs initially but a " { $link <lazy-append> } " object is returned which conforms to the list protocol. Calling " { $link car } ", " { $link cdr } " or " { $link nil? } " on this will evaluate elements as required. Successive calls to " { $link cdr } " will iterate through list1, followed by list2." } ;
HELP: lfrom-by HELP: lfrom-by
{ $values { "n" "an integer" } { "quot" { $quotation "( -- int )" } } { "lazy-from-by" "a lazy list of integers" } } { $values { "n" "an integer" } { "quot" { $quotation "( -- n )" } } { "lazy-from-by" "a lazy list of integers" } }
{ $description "Return an infinite lazy list of values starting from n, with each successive value being the result of applying quot to n." } ; { $description "Return an infinite lazy list of values starting from n, with each successive value being the result of applying quot to n." } ;
HELP: lfrom HELP: lfrom
@ -117,7 +107,7 @@ HELP: lfrom
HELP: seq>list HELP: seq>list
{ $values { "index" "an integer 0 or greater" } { "seq" "a sequence" } { "list" "a list" } } { $values { "index" "an integer 0 or greater" } { "seq" "a sequence" } { "list" "a list" } }
{ $description "Convert the sequence into a list, starting from the 'index' offset into the sequence." } { $description "Convert the sequence into a list, starting from " { $snippet "index" } "." }
{ $see-also >list } ; { $see-also >list } ;
HELP: >list HELP: >list
@ -154,7 +144,7 @@ HELP: lmerge
{ $values { "list1" "a list" } { "list2" "a list" } { "result" "lazy list merging list1 and list2" } } { $values { "list1" "a list" } { "list2" "a list" } { "result" "lazy list merging list1 and list2" } }
{ $description "Return the result of merging the two lists in a lazy manner." } { $description "Return the result of merging the two lists in a lazy manner." }
{ $examples { $examples
{ $example "USING: lists.lazy prettyprint ;" "{ 1 2 3 } >list { 4 5 6 } >list lmerge list>array ." "{ 1 4 2 5 3 6 }" } { $example "USING: lists lists.lazy prettyprint ;" "{ 1 2 3 } >list { 4 5 6 } >list lmerge list>array ." "{ 1 4 2 5 3 6 }" }
} ; } ;
HELP: lcontents HELP: lcontents

View File

@ -178,12 +178,6 @@ M: lazy-filter nil? ( lazy-filter -- bool )
] if ] if
] if ; ] if ;
: list>vector ( list -- vector )
[ [ , ] leach ] V{ } make ;
: list>array ( list -- array )
[ [ , ] leach ] { } make ;
TUPLE: lazy-append list1 list2 ; TUPLE: lazy-append list1 list2 ;
C: <lazy-append> lazy-append C: <lazy-append> lazy-append

View File

@ -54,21 +54,21 @@ ARTICLE: { "lists" "manipulation" } "Manipulating lists"
{ $subsection lcut } ; { $subsection lcut } ;
HELP: cons HELP: cons
{ $values { "car" "the head of the list cell" } { "cdr" "the tail of the list cell" } { "cons" "a cons object" } } { $values { "car" "the head of the list cell" } { "cdr" "the tail of the list cell" } { "cons" list } }
{ $description "Constructs a cons cell." } ; { $description "Constructs a cons cell." } ;
HELP: swons HELP: swons
{ $values { "cdr" "the tail of the list cell" } { "car" "the head of the list cell" } { "cons" "a cons object" } } { $values { "cdr" "the tail of the list cell" } { "car" "the head of the list cell" } { "cons" list } }
{ $description "Constructs a cons cell." } ; { $description "Constructs a cons cell." } ;
{ cons swons uncons unswons } related-words { cons swons uncons unswons } related-words
HELP: car HELP: car
{ $values { "cons" "a cons object" } { "car" "the first item in the list" } } { $values { "cons" list } { "car" "the first item in the list" } }
{ $description "Returns the first item in the list." } ; { $description "Returns the first item in the list." } ;
HELP: cdr HELP: cdr
{ $values { "cons" "a cons object" } { "cdr" "a cons object" } } { $values { "cons" list } { "cdr" list } }
{ $description "Returns the tail of the list." } ; { $description "Returns the tail of the list." } ;
{ car cdr } related-words { car cdr } related-words
@ -86,51 +86,51 @@ HELP: nil?
{ 1list 2list 3list } related-words { 1list 2list 3list } related-words
HELP: 1list HELP: 1list
{ $values { "obj" "an object" } { "cons" "a cons object" } } { $values { "obj" "an object" } { "cons" list } }
{ $description "Create a list with 1 element." } ; { $description "Create a list with 1 element." } ;
HELP: 2list HELP: 2list
{ $values { "a" "an object" } { "b" "an object" } { "cons" "a cons object" } } { $values { "a" "an object" } { "b" "an object" } { "cons" list } }
{ $description "Create a list with 2 elements." } ; { $description "Create a list with 2 elements." } ;
HELP: 3list HELP: 3list
{ $values { "a" "an object" } { "b" "an object" } { "c" "an object" } { "cons" "a cons object" } } { $values { "a" "an object" } { "b" "an object" } { "c" "an object" } { "cons" list } }
{ $description "Create a list with 3 elements." } ; { $description "Create a list with 3 elements." } ;
HELP: lnth HELP: lnth
{ $values { "n" "an integer index" } { "list" "a cons object" } { "elt" "the element at the nth index" } } { $values { "n" "an integer index" } { "list" list } { "elt" "the element at the nth index" } }
{ $description "Outputs the nth element of the list." } { $description "Outputs the nth element of the list." }
{ $see-also llength cons car cdr } ; { $see-also llength cons car cdr } ;
HELP: llength HELP: llength
{ $values { "list" "a cons object" } { "n" "a non-negative integer" } } { $values { "list" list } { "n" "a non-negative integer" } }
{ $description "Outputs the length of the list. This should not be called on an infinite list." } { $description "Outputs the length of the list. This should not be called on an infinite list." }
{ $see-also lnth cons car cdr } ; { $see-also lnth cons car cdr } ;
HELP: uncons HELP: uncons
{ $values { "cons" "a cons object" } { "car" "the head of the list" } { "cdr" "the tail of the list" } } { $values { "cons" list } { "car" "the head of the list" } { "cdr" "the tail of the list" } }
{ $description "Put the head and tail of the list on the stack." } ; { $description "Put the head and tail of the list on the stack." } ;
HELP: unswons HELP: unswons
{ $values { "cons" "a cons object" } { "car" "the head of the list" } { "cdr" "the tail of the list" } } { $values { "cons" list } { "car" "the head of the list" } { "cdr" "the tail of the list" } }
{ $description "Put the head and tail of the list on the stack." } ; { $description "Put the head and tail of the list on the stack." } ;
{ leach foldl lmap>array } related-words { leach foldl lmap>array } related-words
HELP: leach HELP: leach
{ $values { "list" "a cons object" } { "quot" { $quotation "( obj -- )" } } } { $values { "list" list } { "quot" { $quotation "( obj -- )" } } }
{ $description "Call the quotation for each item in the list." } ; { $description "Call the quotation for each item in the list." } ;
HELP: foldl HELP: foldl
{ $values { "list" "a cons object" } { "identity" "an object" } { "quot" { $quotation "( prev elt -- next )" } } { "result" "the final result" } } { $values { "list" list } { "identity" "an object" } { "quot" { $quotation "( prev elt -- next )" } } { "result" "the final result" } }
{ $description "Combines successive elements of the list (in a left-assocative order) using a binary operation and outputs the final result." } ; { $description "Combines successive elements of the list (in a left-assocative order) using a binary operation and outputs the final result." } ;
HELP: foldr HELP: foldr
{ $values { "list" "a cons object" } { "identity" "an object" } { "quot" { $quotation "( prev elt -- next )" } } { "result" "the final result" } } { $values { "list" list } { "identity" "an object" } { "quot" { $quotation "( prev elt -- next )" } } { "result" "the final result" } }
{ $description "Combines successive elements of the list (in a right-assocative order) using a binary operation, and outputs the final result." } ; { $description "Combines successive elements of the list (in a right-assocative order) using a binary operation, and outputs the final result." } ;
HELP: lmap HELP: lmap
{ $values { "list" "a cons object" } { "quot" { $quotation "( old -- new )" } } { "result" "the final result" } } { $values { "list" list } { "quot" { $quotation "( old -- new )" } } { "result" "the final result" } }
{ $description "Applies the quotation to each element of the list in order, collecting the new elements into a new list." } ; { $description "Applies the quotation to each element of the list in order, collecting the new elements into a new list." } ;
HELP: lreverse HELP: lreverse
@ -138,23 +138,15 @@ HELP: lreverse
{ $description "Reverses the input list, outputing a new, reversed list. The output is a strict cons list." } ; { $description "Reverses the input list, outputing a new, reversed list. The output is a strict cons list." } ;
HELP: list>array HELP: list>array
{ $values { "list" "a cons object" } { "array" array } } { $values { "list" list } { "array" array } }
{ $description "Turns the given cons object into an array, maintaing order." } ; { $description "Convert a list into an array." } ;
HELP: sequence>cons
{ $values { "sequence" sequence } { "list" cons } }
{ $description "Turns the given array into a cons object, maintaing order." } ;
HELP: deep-list>array HELP: deep-list>array
{ $values { "list" list } { "array" array } } { $values { "list" list } { "array" array } }
{ $description "Recursively turns the given cons object into an array, maintaing order and also converting nested lists." } ; { $description "Recursively turns the given cons object into an array, maintaining order and also converting nested lists." } ;
HELP: deep-sequence>cons
{ $values { "sequence" sequence } { "cons" cons } }
{ $description "Recursively turns the given sequence into a cons object, maintaing order and also converting nested lists." } ;
HELP: traverse HELP: traverse
{ $values { "list" "a cons object" } { "pred" { $quotation "( list/elt -- ? )" } } { $values { "list" list } { "pred" { $quotation "( list/elt -- ? )" } }
{ "quot" { $quotation "( list/elt -- result)" } } { "result" "a new cons object" } } { "quot" { $quotation "( list/elt -- result)" } } { "result" "a new cons object" } }
{ $description "Recursively traverses the list object, replacing any elements (which can themselves be sublists) that pred" { $description "Recursively traverses the list object, replacing any elements (which can themselves be sublists) that pred"
" returns true for with the result of applying quot to." } ; " returns true for with the result of applying quot to." } ;

View File

@ -1,6 +1,6 @@
! Copyright (C) 2008 James Cash ! Copyright (C) 2008 James Cash
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: tools.test lists math kernel ; USING: tools.test lists lists.lazy math kernel ;
IN: lists.tests IN: lists.tests
{ { 3 4 5 6 7 } } [ { { 3 4 5 6 7 } } [
@ -23,49 +23,24 @@ IN: lists.tests
+nil+ } } } } 0 [ + ] foldl +nil+ } } } } 0 [ + ] foldl
] unit-test ] unit-test
{ T{ cons f
1
T{ cons f
2
T{ cons f
T{ cons f
3
T{ cons f
4
T{ cons f
T{ cons f 5 +nil+ }
+nil+ } } }
+nil+ } } }
} [
{ 1 2 { 3 4 { 5 } } } deep-sequence>cons
] unit-test
{ { 1 2 { 3 4 { 5 } } } } [
{ 1 2 { 3 4 { 5 } } } deep-sequence>cons deep-list>array
] unit-test
{ T{ cons f 2 T{ cons f 3 T{ cons f 4 T{ cons f 5 +nil+ } } } } } [ { T{ cons f 2 T{ cons f 3 T{ cons f 4 T{ cons f 5 +nil+ } } } } } [
{ 1 2 3 4 } sequence>cons [ 1+ ] lmap { 1 2 3 4 } seq>list [ 1+ ] lmap
] unit-test ] unit-test
{ 15 } [ { 15 } [
{ 1 2 3 4 5 } sequence>cons 0 [ + ] foldr { 1 2 3 4 5 } seq>list 0 [ + ] foldr
] unit-test ] unit-test
{ { 5 4 3 2 1 } } [ { { 5 4 3 2 1 } } [
{ 1 2 3 4 5 } sequence>cons lreverse list>array { 1 2 3 4 5 } seq>list lreverse list>array
] unit-test ] unit-test
{ 5 } [ { 5 } [
{ 1 2 3 4 5 } sequence>cons llength { 1 2 3 4 5 } seq>list llength
] unit-test
{ { 3 4 { 5 6 { 7 } } } } [
{ 1 2 { 3 4 { 5 } } } deep-sequence>cons [ atom? ] [ 2 + ] traverse deep-list>array
] unit-test ] unit-test
{ { 1 2 3 4 5 6 } } [ { { 1 2 3 4 5 6 } } [
{ 1 2 3 } sequence>cons { 4 5 6 } sequence>cons lappend list>array { 1 2 3 } seq>list { 4 5 6 } seq>list lappend list>array
] unit-test ] unit-test
[ { 1 } { 2 } ] [ { 1 2 } sequence>cons 1 lcut [ list>array ] bi@ ] unit-test [ { 1 } { 2 } ] [ { 1 2 } seq>list 1 lcut [ list>array ] bi@ ] unit-test

View File

@ -65,7 +65,7 @@ ${ five six 7 } .
ARTICLE: "literals" "Interpolating code results into literal values" ARTICLE: "literals" "Interpolating code results into literal values"
"The " { $vocab-link "literals" } " vocabulary contains words to run code at parse time and insert the results into more complex literal values." "The " { $vocab-link "literals" } " vocabulary contains words to run code at parse time and insert the results into more complex literal values."
{ $example <" { $example <"
USING: kernel literals math prettyprint ; USE: literals
IN: scratchpad IN: scratchpad
CONSTANT: five 5 CONSTANT: five 5

View File

@ -4,9 +4,9 @@ IN: math.complex
ARTICLE: "complex-numbers-zero" "Embedding of real numbers in complex numbers" ARTICLE: "complex-numbers-zero" "Embedding of real numbers in complex numbers"
"Constructing a complex number with an imaginary component equal to an integer zero simply returns the real number corresponding to the real component:" "Constructing a complex number with an imaginary component equal to an integer zero simply returns the real number corresponding to the real component:"
{ $example "USING: math prettyprint ;" "C{ 1 2 } C{ 3 -2 } + ." "4" } { $example "C{ 1 2 } C{ 3 -2 } + ." "4" }
"Constructing a complex number with an imaginary component equal to floating point zero will still output a new complex number, however:" "Constructing a complex number with an imaginary component equal to floating point zero will still output a new complex number, however:"
{ $example "USING: math prettyprint ;" "C{ 0.0 2.0 } C{ 0.0 1.0 } * ." "C{ -2.0 0.0 }" } { $example "C{ 0.0 2.0 } C{ 0.0 1.0 } * ." "C{ -2.0 0.0 }" }
"Unlike math, where all real numbers are also complex numbers, Factor only considers a number to be a complex number if its imaginary part is non-zero. However, complex number operations are fully supported for real numbers; they are treated as having an imaginary part of zero." ; "Unlike math, where all real numbers are also complex numbers, Factor only considers a number to be a complex number if its imaginary part is non-zero. However, complex number operations are fully supported for real numbers; they are treated as having an imaginary part of zero." ;
ARTICLE: "complex-numbers" "Complex numbers" ARTICLE: "complex-numbers" "Complex numbers"

View File

@ -1,8 +1,7 @@
! Copyright (C) 2009 Slava Pestov. ! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: tools.test opengl.textures opengl.textures.private USING: tools.test opengl.textures opengl.textures.private
opengl.textures.private images kernel namespaces accessors images kernel namespaces accessors sequences ;
sequences ;
IN: opengl.textures.tests IN: opengl.textures.tests
[ [

View File

@ -461,7 +461,7 @@ M: ebnf-sequence build-locals ( code ast -- code )
M: ebnf-var build-locals ( code ast -- ) M: ebnf-var build-locals ( code ast -- )
[ [
"FROM: locals => [let* ; FROM: kernel => dup ; [let* | " % "FROM: locals => [let* ; FROM: kernel => dup nip ; [let* | " %
name>> % " [ dup ] " % name>> % " [ dup ] " %
" | " % " | " %
% %

View File

@ -2,7 +2,7 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
! !
USING: kernel tools.test strings namespaces make arrays sequences USING: kernel tools.test strings namespaces make arrays sequences
peg peg.private peg.parsers accessors words math accessors ; peg peg.private peg.parsers words math accessors ;
IN: peg.tests IN: peg.tests
[ ] [ reset-pegs ] unit-test [ ] [ reset-pegs ] unit-test

View File

@ -91,15 +91,13 @@ unit-test
: check-see ( expect name -- ? ) : check-see ( expect name -- ? )
[ [
use [ clone ] change
[ [
[ parse-fresh drop ] with-compilation-unit [ parse-fresh drop ] with-compilation-unit
[ [
"prettyprint.tests" lookup see "prettyprint.tests" lookup see
] with-string-writer "\n" split but-last ] with-string-writer "\n" split but-last
] keep = ] keep =
] with-scope ; ] with-interactive-vocabs ;
GENERIC: method-layout ( a -- b ) GENERIC: method-layout ( a -- b )

View File

@ -31,7 +31,7 @@ ARTICLE: { "regexp" "intro" } "A quick introduction to regular expressions"
"To search a file for all lines that match a given regular expression, you could use code like this:" "To search a file for all lines that match a given regular expression, you could use code like this:"
{ $code <" "file.txt" ascii file-lines [ R/ (f|b)oo+/ re-contains? ] filter "> } { $code <" "file.txt" ascii file-lines [ R/ (f|b)oo+/ re-contains? ] filter "> }
"To test if a string in its entirety matches a regular expression, the following can be used:" "To test if a string in its entirety matches a regular expression, the following can be used:"
{ $example <" USING: regexp prettyprint ; "fooo" R/ (b|f)oo+/ matches? . "> "t" } { $example <" USE: regexp "fooo" R/ (b|f)oo+/ matches? . "> "t" }
"Regular expressions can't be used for all parsing tasks. For example, they are not powerful enough to match balancing parentheses." ; "Regular expressions can't be used for all parsing tasks. For example, they are not powerful enough to match balancing parentheses." ;
ARTICLE: { "regexp" "construction" } "Constructing regular expressions" ARTICLE: { "regexp" "construction" } "Constructing regular expressions"

View File

@ -1,7 +1,7 @@
! Copyright (C) 2006 Chris Double. ! Copyright (C) 2006 Chris Double.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
! !
USING: tools.test kernel serialize io io.streams.byte-array math USING: tools.test kernel serialize io io.streams.byte-array
alien arrays byte-arrays bit-arrays specialized-arrays.double alien arrays byte-arrays bit-arrays specialized-arrays.double
sequences math prettyprint parser classes math.constants sequences math prettyprint parser classes math.constants
io.encodings.binary random assocs serialize.private ; io.encodings.binary random assocs serialize.private ;

View File

@ -1,4 +1,4 @@
USING: stack-checker.call-effect tools.test math kernel math effects ; USING: stack-checker.call-effect tools.test kernel math effects ;
IN: stack-checker.call-effect.tests IN: stack-checker.call-effect.tests
[ t ] [ \ + (( a b -- c )) execute-effect-unsafe? ] unit-test [ t ] [ \ + (( a b -- c )) execute-effect-unsafe? ] unit-test

View File

@ -1,7 +1,6 @@
IN: struct-arrays.tests IN: struct-arrays.tests
USING: struct-arrays tools.test kernel math sequences USING: struct-arrays tools.test kernel math sequences
alien.syntax alien.c-types destructors libc accessors alien.syntax alien.c-types destructors libc accessors ;
destructors ;
C-STRUCT: test-struct C-STRUCT: test-struct
{ "int" "x" } { "int" "x" }

View File

@ -1,8 +1,7 @@
USING: accessors ui.gadgets ui.gadgets.private ui.gadgets.packs USING: accessors ui.gadgets ui.gadgets.packs ui.gadgets.worlds
ui.gadgets.worlds tools.test namespaces models kernel dlists deques tools.test namespaces models kernel dlists deques math
math sets math.parser ui sequences hashtables assocs io arrays math.parser ui sequences hashtables assocs io arrays prettyprint
prettyprint io.streams.string math.rectangles ui.gadgets.private io.streams.string math.rectangles ui.gadgets.private sets generic ;
sets generic ;
IN: ui.gadgets.tests IN: ui.gadgets.tests
[ { 300 300 } ] [ { 300 300 } ]

View File

@ -2,7 +2,7 @@ USING: continuations documents
ui.tools.listener hashtables kernel namespaces parser sequences ui.tools.listener hashtables kernel namespaces parser sequences
tools.test ui.commands ui.gadgets ui.gadgets.editors tools.test ui.commands ui.gadgets ui.gadgets.editors
ui.gadgets.panes vocabs words ui.gadgets.debug slots.private ui.gadgets.panes vocabs words ui.gadgets.debug slots.private
threads arrays generic threads accessors listener math arrays generic threads accessors listener math
calendar concurrency.promises io ui.tools.common ; calendar concurrency.promises io ui.tools.common ;
IN: ui.tools.listener.tests IN: ui.tools.listener.tests
@ -146,7 +146,7 @@ CONSTANT: text "Hello world.\nThis is a test."
[ ] [ "listener" get com-end ] unit-test [ ] [ "listener" get com-end ] unit-test
] with-grafted-gadget ] with-grafted-gadget
[ ] [ \ + <interactor> vocabs>> use-if-necessary ] unit-test [ ] [ \ + <interactor> manifest>> use-if-necessary ] unit-test
[ ] [ <listener-gadget> "l" set ] unit-test [ ] [ <listener-gadget> "l" set ] unit-test
[ ] [ "l" get com-scroll-up ] unit-test [ ] [ "l" get com-scroll-up ] unit-test

View File

@ -50,7 +50,7 @@ ARTICLE: { "xml.syntax" "interpolation" } "XML interpolation syntax"
$nl $nl
"These forms can be used where a tag might go, as in " { $snippet "[XML <foo><-></foo> XML]" } " or where an attribute might go, as in " { $snippet "[XML <foo bar=<->/> XML]" } ". When an attribute is spliced in, it is not included if the value is " { $snippet "f" } " and if the value is not a string, the value is put through " { $link present } ". Here is an example of the fry style of XML interpolation:" "These forms can be used where a tag might go, as in " { $snippet "[XML <foo><-></foo> XML]" } " or where an attribute might go, as in " { $snippet "[XML <foo bar=<->/> XML]" } ". When an attribute is spliced in, it is not included if the value is " { $snippet "f" } " and if the value is not a string, the value is put through " { $link present } ". Here is an example of the fry style of XML interpolation:"
{ $example { $example
{" USING: splitting sequences xml.writer xml.syntax ; {" USING: splitting xml.writer xml.syntax ;
"one two three" " " split "one two three" " " split
[ [XML <item><-></item> XML] ] map [ [XML <item><-></item> XML] ] map
<XML <doc><-></doc> XML> pprint-xml"} <XML <doc><-></doc> XML> pprint-xml"}
@ -86,7 +86,7 @@ $nl
{" <?xml version="1.0" encoding="UTF-8"?> {" <?xml version="1.0" encoding="UTF-8"?>
<x number="3" url="http://factorcode.org/" string="hello" word="drop"/>"} } <x number="3" url="http://factorcode.org/" string="hello" word="drop"/>"} }
"XML interpolation can also be used, in conjunction with " { $vocab-link "inverse" } " in pattern matching. For example:" "XML interpolation can also be used, in conjunction with " { $vocab-link "inverse" } " in pattern matching. For example:"
{ $example {" USING: sequences xml.syntax inverse ; { $example {" USING: xml.syntax inverse ;
: dispatch ( xml -- string ) : dispatch ( xml -- string )
{ {
{ [ [XML <a><-></a> XML] ] [ "a" prepend ] } { [ [XML <a><-></a> XML] ] [ "a" prepend ] }

View File

@ -100,8 +100,6 @@ XML-NS: foo http://blah.com
[ "" ] [ [XML XML] concat ] unit-test [ "" ] [ [XML XML] concat ] unit-test
USE: inverse
[ "foo" ] [ [XML <a>foo</a> XML] [ [XML <a><-></a> XML] ] undo ] unit-test [ "foo" ] [ [XML <a>foo</a> XML] [ [XML <a><-></a> XML] ] undo ] unit-test
[ "foo" ] [ [XML <a bar='foo'/> XML] [ [XML <a bar=<-> /> XML] ] undo ] unit-test [ "foo" ] [ [XML <a bar='foo'/> XML] [ [XML <a bar=<-> /> XML] ] undo ] unit-test
[ "foo" "baz" ] [ [XML <a bar='foo'>baz</a> XML] [ [XML <a bar=<->><-></a> XML] ] undo ] unit-test [ "foo" "baz" ] [ [XML <a bar='foo'>baz</a> XML] [ [XML <a bar=<->><-></a> XML] ] undo ] unit-test

View File

@ -21,7 +21,7 @@ ARTICLE: "enums" "Enumerations"
{ $subsection enum } { $subsection enum }
{ $subsection <enum> } { $subsection <enum> }
"Inverting a permutation using enumerations:" "Inverting a permutation using enumerations:"
{ $example "USING: assocs sorting prettyprint ;" "IN: scratchpad" ": invert ( perm -- perm' )" " <enum> >alist sort-values keys ;" "{ 2 0 4 1 3 } invert ." "{ 1 3 0 4 2 }" } ; { $example "IN: scratchpad" ": invert ( perm -- perm' )" " <enum> >alist sort-values keys ;" "{ 2 0 4 1 3 } invert ." "{ 1 3 0 4 2 }" } ;
HELP: enum HELP: enum
{ $class-description "An associative structure which wraps a sequence and maps integers to the corresponding elements of the sequence." { $class-description "An associative structure which wraps a sequence and maps integers to the corresponding elements of the sequence."

View File

@ -51,6 +51,7 @@ IN: bootstrap.syntax
"UNION:" "UNION:"
"INTERSECTION:" "INTERSECTION:"
"USE:" "USE:"
"UNUSE:"
"USING:" "USING:"
"QUALIFIED:" "QUALIFIED:"
"QUALIFIED-WITH:" "QUALIFIED-WITH:"

View File

@ -1,6 +1,6 @@
USING: alien arrays definitions generic assocs hashtables io USING: alien arrays definitions generic assocs hashtables io
kernel math namespaces parser prettyprint sequences strings kernel math namespaces parser prettyprint sequences strings
tools.test vectors words quotations classes classes.algebra tools.test words quotations classes classes.algebra
classes.private classes.union classes.mixin classes.predicate classes.private classes.union classes.mixin classes.predicate
vectors definitions source-files compiler.units growable vectors definitions source-files compiler.units growable
random stack-checker effects kernel.private sbufs math.order random stack-checker effects kernel.private sbufs math.order

View File

@ -1,4 +1,4 @@
USING: alien arrays definitions generic assocs hashtables io USING: alien arrays generic assocs hashtables io
io.streams.string kernel math namespaces parser prettyprint io.streams.string kernel math namespaces parser prettyprint
sequences strings tools.test vectors words quotations classes sequences strings tools.test vectors words quotations classes
classes.private classes.union classes.mixin classes.predicate classes.private classes.union classes.mixin classes.predicate

View File

@ -1,9 +1,8 @@
USING: alien arrays definitions generic assocs hashtables io USING: alien arrays definitions generic assocs hashtables io kernel
kernel math namespaces parser prettyprint sequences strings math namespaces parser prettyprint sequences strings tools.test words
tools.test vectors words quotations classes quotations classes classes.private classes.union classes.mixin
classes.private classes.union classes.mixin classes.predicate classes.predicate classes.algebra vectors source-files compiler.units
classes.algebra vectors definitions source-files kernel.private sorting vocabs eval ;
compiler.units kernel.private sorting vocabs eval ;
IN: classes.mixin.tests IN: classes.mixin.tests
! Test mixins ! Test mixins

View File

@ -29,6 +29,6 @@ PREDICATE: tuple-c < tuple-b slot>> ;
GENERIC: ptest ( tuple -- ) GENERIC: ptest ( tuple -- )
M: tuple-a ptest drop ; M: tuple-a ptest drop ;
IN: classes.predicate.tests USING: kernel ; M: tuple-c ptest drop ; M: tuple-c ptest drop ;
[ ] [ tuple-b new ptest ] unit-test [ ] [ tuple-b new ptest ] unit-test

View File

@ -152,7 +152,6 @@ ARTICLE: "compositional-examples" "Examples of compositional combinator usage"
{ $code ": subtract-n ( seq n -- seq' ) swap [ over - ] map nip ;" } { $code ": subtract-n ( seq n -- seq' ) swap [ over - ] map nip ;" }
"Three shuffle words are required to pass the value around. Instead, the loop-invariant value can be partially applied to a quotation using " { $link curry } ", yielding a new quotation that is passed to " { $link map } ":" "Three shuffle words are required to pass the value around. Instead, the loop-invariant value can be partially applied to a quotation using " { $link curry } ", yielding a new quotation that is passed to " { $link map } ":"
{ $example { $example
"USING: kernel math prettyprint sequences ;"
": subtract-n ( seq n -- seq' ) [ - ] curry map ;" ": subtract-n ( seq n -- seq' ) [ - ] curry map ;"
"{ 10 20 30 } 5 subtract-n ." "{ 10 20 30 } 5 subtract-n ."
"{ 5 15 25 }" "{ 5 15 25 }"
@ -163,7 +162,6 @@ $nl
{ $code ": n-subtract ( n seq -- seq' ) swap [ swap - ] curry map ;" } { $code ": n-subtract ( n seq -- seq' ) swap [ swap - ] curry map ;" }
"Since this pattern comes up often, " { $link with } " encapsulates it:" "Since this pattern comes up often, " { $link with } " encapsulates it:"
{ $example { $example
"USING: kernel math prettyprint sequences ;"
": n-subtract ( n seq -- seq' ) [ - ] with map ;" ": n-subtract ( n seq -- seq' ) [ - ] with map ;"
"30 { 10 20 30 } n-subtract ." "30 { 10 20 30 } n-subtract ."
"{ 20 10 0 }" "{ 20 10 0 }"

View File

@ -48,7 +48,7 @@ $nl
"The accumulator sequence can be accessed directly from inside a " { $link make } ":" "The accumulator sequence can be accessed directly from inside a " { $link make } ":"
{ $subsection building } { $subsection building }
{ $example { $example
"USING: make math.parser io ;" "USING: make math.parser ;"
"[ \"Language #\" % CHAR: \\s , 5 # ] \"\" make print" "[ \"Language #\" % CHAR: \\s , 5 # ] \"\" make print"
"Language # 5" "Language # 5"
} }

View File

@ -1,7 +1,7 @@
USING: help.markup help.syntax kernel sequences words USING: help.markup help.syntax kernel sequences words
math strings vectors quotations generic effects classes math strings vectors quotations generic effects classes
vocabs.loader definitions io vocabs source-files vocabs.loader definitions io vocabs source-files
quotations namespaces compiler.units assocs lexer namespaces compiler.units assocs lexer
words.symbol words.alias words.constant vocabs.parser ; words.symbol words.alias words.constant vocabs.parser ;
IN: parser IN: parser
@ -70,7 +70,8 @@ $nl
{ $subsection "reading-ahead" } { $subsection "reading-ahead" }
{ $subsection "parsing-word-nest" } { $subsection "parsing-word-nest" }
{ $subsection "defining-words" } { $subsection "defining-words" }
{ $subsection "parsing-tokens" } ; { $subsection "parsing-tokens" }
{ $subsection "word-search-parsing" } ;
ARTICLE: "parser-files" "Parsing source files" ARTICLE: "parser-files" "Parsing source files"
"The parser can run source files:" "The parser can run source files:"
@ -84,7 +85,7 @@ $nl
ARTICLE: "top-level-forms" "Top level forms" ARTICLE: "top-level-forms" "Top level forms"
"Any code outside of a definition is known as a " { $emphasis "top-level form" } "; top-level forms are run after the entire source file has been parsed, regardless of their position in the file." "Any code outside of a definition is known as a " { $emphasis "top-level form" } "; top-level forms are run after the entire source file has been parsed, regardless of their position in the file."
$nl $nl
"Top-level forms do not have access to the " { $link in } " and " { $link use } " variables that were set at parse time, nor do they run inside " { $link with-compilation-unit } "; so meta-programming might require extra work in a top-level form compared with a parsing word." "Top-level forms cannot access the parse-time manifest (" { $link "word-search-parsing" } "), nor do they run inside " { $link with-compilation-unit } "; as a result, meta-programming might require extra work in a top-level form compared with a parsing word."
$nl $nl
"Also, top-level forms run in a new dynamic scope, so using " { $link set } " to store values is almost always wrong, since the values will be lost after the top-level form completes. To save values computed by a top-level form, either use " { $link set-global } " or define a new word with the value." ; "Also, top-level forms run in a new dynamic scope, so using " { $link set } " to store values is almost always wrong, since the values will be lost after the top-level form completes. To save values computed by a top-level form, either use " { $link set-global } " or define a new word with the value." ;
@ -119,8 +120,6 @@ HELP: parser-notes?
HELP: bad-number HELP: bad-number
{ $error-description "Indicates the parser encountered an invalid numeric literal." } ; { $error-description "Indicates the parser encountered an invalid numeric literal." } ;
{ use in add-use (add-use) set-use set-in POSTPONE: USING: POSTPONE: USE: with-file-vocabs with-interactive-vocabs } related-words
HELP: create-in HELP: create-in
{ $values { "str" "a word name" } { "word" "a new word" } } { $values { "str" "a word name" } { "word" "a new word" } }
{ $description "Creates a word in the current vocabulary. Until re-defined, the word throws an error when invoked." } { $description "Creates a word in the current vocabulary. Until re-defined, the word throws an error when invoked." }
@ -247,4 +246,4 @@ HELP: staging-violation
HELP: auto-use? HELP: auto-use?
{ $var-description "If set to a true value, the behavior of the parser when encountering an unknown word name is changed. If only one loaded vocabulary has a word with this name, instead of throwing an error, the parser adds the vocabulary to the search path and prints a parse note. Off by default." } { $var-description "If set to a true value, the behavior of the parser when encountering an unknown word name is changed. If only one loaded vocabulary has a word with this name, instead of throwing an error, the parser adds the vocabulary to the search path and prints a parse note. Off by default." }
{ $notes "This feature is intended to help during development. To generate a " { $link POSTPONE: USING: } " form automatically, enable " { $link auto-use? } ", load the source file, and copy and paste the " { $link POSTPONE: USING: } " form printed by the parser back into the file, then disable " { $link auto-use? } ". See " { $link "vocabulary-search-errors" } "." } ; { $notes "This feature is intended to help during development. To generate a " { $link POSTPONE: USING: } " form automatically, enable " { $link auto-use? } ", load the source file, and copy and paste the " { $link POSTPONE: USING: } " form printed by the parser back into the file, then disable " { $link auto-use? } ". See " { $link "word-search-errors" } "." } ;

View File

@ -87,18 +87,6 @@ IN: parser.tests
[ "OCT: 999" eval( -- obj ) ] must-fail [ "OCT: 999" eval( -- obj ) ] must-fail
[ "BIN: --0" eval( -- obj ) ] must-fail [ "BIN: --0" eval( -- obj ) ] must-fail
! Another funny bug
[ t ] [
[
"scratchpad" in set
{ "scratchpad" "arrays" } set-use
[
! This shouldn't modify in/use in the outer scope!
] with-file-vocabs
use get { "scratchpad" "arrays" } set-use use get =
] with-scope
] unit-test
DEFER: foo DEFER: foo
"IN: parser.tests USING: math prettyprint ; SYNTAX: foo 2 2 + . ;" eval( -- ) "IN: parser.tests USING: math prettyprint ; SYNTAX: foo 2 2 + . ;" eval( -- )
@ -596,7 +584,7 @@ EXCLUDE: qualified.tests.bar => x ;
] unit-test ] unit-test
[ [ ] ] [ [ [ ] ] [
"IN: parser.tests.forward-ref-3 USING: parser.tests.forward-ref-1 parser.tests.forward-ref-2 ; : z ( -- ) x y ;" "IN: parser.tests.forward-ref-3 FROM: parser.tests.forward-ref-1 => x y ; FROM: parser.tests.forward-ref-2 => x y ; : z ( -- ) x y ;"
<string-reader> "forward-ref-3" parse-stream <string-reader> "forward-ref-3" parse-stream
] unit-test ] unit-test
@ -605,7 +593,7 @@ EXCLUDE: qualified.tests.bar => x ;
] unit-test ] unit-test
[ [ ] ] [ [ [ ] ] [
"USING: parser.tests.forward-ref-1 parser.tests.forward-ref-2 ; IN: parser.tests.forward-ref-3 : x ( -- ) ; : z ( -- ) x y ;" "FROM: parser.tests.forward-ref-1 => x y ; FROM: parser.tests.forward-ref-2 => x y ; IN: parser.tests.forward-ref-3 : x ( -- ) ; : z ( -- ) x y ;"
<string-reader> "forward-ref-3" parse-stream <string-reader> "forward-ref-3" parse-stream
] unit-test ] unit-test
@ -614,7 +602,7 @@ EXCLUDE: qualified.tests.bar => x ;
] unit-test ] unit-test
[ [ ] ] [ [ [ ] ] [
"IN: parser.tests.forward-ref-3 USING: parser.tests.forward-ref-1 parser.tests.forward-ref-2 ; : z ( -- ) x y ;" "IN: parser.tests.forward-ref-3 FROM: parser.tests.forward-ref-1 => x y ; FROM: parser.tests.forward-ref-2 => x y ; : z ( -- ) x y ;"
<string-reader> "forward-ref-3" parse-stream <string-reader> "forward-ref-3" parse-stream
] unit-test ] unit-test

View File

@ -1,7 +1,8 @@
USING: generic help.syntax help.markup kernel math parser words USING: generic help.syntax help.markup kernel math parser words
effects classes generic.standard classes.tuple generic.math effects classes generic.standard classes.tuple generic.math
generic.standard generic.single arrays io.pathnames vocabs.loader io generic.standard generic.single arrays io.pathnames vocabs.loader io
sequences assocs words.symbol words.alias words.constant combinators ; sequences assocs words.symbol words.alias words.constant combinators
vocabs.parser ;
IN: syntax IN: syntax
ARTICLE: "parser-algorithm" "Parser algorithm" ARTICLE: "parser-algorithm" "Parser algorithm"
@ -179,7 +180,7 @@ $nl
ARTICLE: "syntax" "Syntax" ARTICLE: "syntax" "Syntax"
"Factor has two main forms of syntax: " { $emphasis "definition" } " syntax and " { $emphasis "literal" } " syntax. Code is data, so the syntax for code is a special case of object literal syntax. This section documents literal syntax. Definition syntax is covered in " { $link "words" } ". Extending the parser is the main topic of " { $link "parser" } "." "Factor has two main forms of syntax: " { $emphasis "definition" } " syntax and " { $emphasis "literal" } " syntax. Code is data, so the syntax for code is a special case of object literal syntax. This section documents literal syntax. Definition syntax is covered in " { $link "words" } ". Extending the parser is the main topic of " { $link "parser" } "."
{ $subsection "parser-algorithm" } { $subsection "parser-algorithm" }
{ $subsection "vocabulary-search" } { $subsection "word-search" }
{ $subsection "top-level-forms" } { $subsection "top-level-forms" }
{ $subsection "syntax-comments" } { $subsection "syntax-comments" }
{ $subsection "syntax-literals" } { $subsection "syntax-literals" }
@ -427,18 +428,33 @@ HELP: FORGET:
HELP: USE: HELP: USE:
{ $syntax "USE: vocabulary" } { $syntax "USE: vocabulary" }
{ $values { "vocabulary" "a vocabulary name" } } { $values { "vocabulary" "a vocabulary name" } }
{ $description "Adds a new vocabulary at the front of the search path. Subsequent word lookups by the parser will search this vocabulary first." } { $description "Adds a new vocabulary to the search path, loading it first if necessary." }
{ $notes "If adding the vocabulary introduces ambiguity, referencing the ambiguous names will throw a " { $link ambiguous-use-error } "." }
{ $errors "Throws an error if the vocabulary does not exist or could not be loaded." } ;
HELP: UNUSE:
{ $syntax "UNUSE: vocabulary" }
{ $values { "vocabulary" "a vocabulary name" } }
{ $description "Removes a vocabulary from the search path." }
{ $errors "Throws an error if the vocabulary does not exist." } ; { $errors "Throws an error if the vocabulary does not exist." } ;
HELP: USING: HELP: USING:
{ $syntax "USING: vocabularies... ;" } { $syntax "USING: vocabularies... ;" }
{ $values { "vocabularies" "a list of vocabulary names" } } { $values { "vocabularies" "a list of vocabulary names" } }
{ $description "Adds a list of vocabularies to the front of the search path, with later vocabularies taking precedence." } { $description "Adds a list of vocabularies to the search path." }
{ $notes "If adding the vocabularies introduces ambiguity, referencing the ambiguous names will throw a " { $link ambiguous-use-error } "." }
{ $errors "Throws an error if one of the vocabularies does not exist." } ; { $errors "Throws an error if one of the vocabularies does not exist." } ;
HELP: QUALIFIED: HELP: QUALIFIED:
{ $syntax "QUALIFIED: vocab" } { $syntax "QUALIFIED: vocab" }
{ $description "Similar to " { $link POSTPONE: USE: } " but loads vocabulary with prefix." } { $description "Adds the vocabulary's words, prefixed with the vocabulary name, to the search path." }
{ $notes "If adding the vocabulary introduces ambiguity, the vocabulary will take precedence when resolving any ambiguous names. This is a rare case; for example, suppose a vocabulary " { $snippet "fish" } " defines a word named " { $snippet "go:fishing" } ", and a vocabulary named " { $snippet "go" } " defines a word named " { $snippet "finishing" } ". Then, the following will call the latter word:"
{ $code
"USE: fish"
"QUALIFIED: go"
"go:fishing"
}
}
{ $examples { $example { $examples { $example
"USING: prettyprint ;" "USING: prettyprint ;"
"QUALIFIED: math" "QUALIFIED: math"
@ -447,7 +463,7 @@ HELP: QUALIFIED:
HELP: QUALIFIED-WITH: HELP: QUALIFIED-WITH:
{ $syntax "QUALIFIED-WITH: vocab word-prefix" } { $syntax "QUALIFIED-WITH: vocab word-prefix" }
{ $description "Works like " { $link POSTPONE: QUALIFIED: } " but uses " { $snippet "word-prefix" } " as prefix." } { $description "Like " { $link POSTPONE: QUALIFIED: } " but uses " { $snippet "word-prefix" } " as prefix." }
{ $examples { $code { $examples { $code
"USING: prettyprint ;" "USING: prettyprint ;"
"QUALIFIED-WITH: math m" "QUALIFIED-WITH: math m"
@ -457,19 +473,25 @@ HELP: QUALIFIED-WITH:
HELP: FROM: HELP: FROM:
{ $syntax "FROM: vocab => words ... ;" } { $syntax "FROM: vocab => words ... ;" }
{ $description "Imports " { $snippet "words" } " from " { $snippet "vocab" } "." } { $description "Adds " { $snippet "words" } " from " { $snippet "vocab" } " to the search path." }
{ $examples { $code { $notes "If adding the words introduces ambiguity, the words will take precedence when resolving any ambiguous names." }
"FROM: math.parser => bin> hex> ; ! imports only bin> and hex>" } } ; { $examples
"Both the " { $vocab-link "vocabs.parser" } " and " { $vocab-link "binary-search" } " vocabularies define a word named " { $snippet "search" } ". The following will throw an " { $link ambiguous-use-error } ":"
{ $code "USING: vocabs.parser binary-search ;" "... search ..." }
"Because " { $link POSTPONE: FROM: } " takes precedence over a " { $link POSTPONE: USING: } ", the ambiguity can be resolved explicitly. Suppose you wanted the " { $vocab-link "binary-search" } " vocabulary's " { $snippet "search" } " word:"
{ $code "USING: vocabs.parser binary-search ;" "FROM: binary-search => search ;" "... search ..." }
} ;
HELP: EXCLUDE: HELP: EXCLUDE:
{ $syntax "EXCLUDE: vocab => words ... ;" } { $syntax "EXCLUDE: vocab => words ... ;" }
{ $description "Imports everything from " { $snippet "vocab" } " excluding " { $snippet "words" } "." } { $description "Adds all words except for " { $snippet "words" } " from " { $snippet "vocab" } " to the search path." }
{ $examples { $code { $examples { $code
"EXCLUDE: math.parser => bin> hex> ; ! imports everything but bin> and hex>" } } ; "EXCLUDE: math.parser => bin> hex> ;" "! imports everything but bin> and hex>" } } ;
HELP: RENAME: HELP: RENAME:
{ $syntax "RENAME: word vocab => newname" } { $syntax "RENAME: word vocab => new-name" }
{ $description "Imports " { $snippet "word" } " from " { $snippet "vocab" } ", but renamed to " { $snippet "newname" } "." } { $description "Imports " { $snippet "word" } " from " { $snippet "vocab" } ", but renamed to " { $snippet "new-name" } "." }
{ $notes "If adding the words introduces ambiguity, the words will take precedence when resolving any ambiguous names." }
{ $examples { $example { $examples { $example
"USING: prettyprint ;" "USING: prettyprint ;"
"RENAME: + math => -" "RENAME: + math => -"
@ -740,7 +762,7 @@ HELP: MAIN:
HELP: <PRIVATE HELP: <PRIVATE
{ $syntax "<PRIVATE ... PRIVATE>" } { $syntax "<PRIVATE ... PRIVATE>" }
{ $description "Marks the start of a block of private word definitions. Private word definitions are placed in a vocabulary named by suffixing the current vocabulary with " { $snippet ".private" } "." } { $description "Begins a block of private word definitions. Private word definitions are placed in the current vocabulary name, suffixed with " { $snippet ".private" } "." }
{ $notes { $notes
"The following is an example of usage:" "The following is an example of usage:"
{ $code { $code
@ -770,7 +792,7 @@ HELP: <PRIVATE
HELP: PRIVATE> HELP: PRIVATE>
{ $syntax "<PRIVATE ... PRIVATE>" } { $syntax "<PRIVATE ... PRIVATE>" }
{ $description "Marks the end of a block of private word definitions." } ; { $description "Ends a block of private word definitions." } ;
{ POSTPONE: <PRIVATE POSTPONE: PRIVATE> } related-words { POSTPONE: <PRIVATE POSTPONE: PRIVATE> } related-words

View File

@ -49,6 +49,8 @@ IN: bootstrap.syntax
"USE:" [ scan use-vocab ] define-core-syntax "USE:" [ scan use-vocab ] define-core-syntax
"UNUSE:" [ scan unuse-vocab ] define-core-syntax
"USING:" [ ";" parse-tokens [ use-vocab ] each ] define-core-syntax "USING:" [ ";" parse-tokens [ use-vocab ] each ] define-core-syntax
"QUALIFIED:" [ scan dup add-qualified ] define-core-syntax "QUALIFIED:" [ scan dup add-qualified ] define-core-syntax

View File

@ -1,43 +1,7 @@
USING: help.markup help.syntax parser strings words ; USING: help.markup help.syntax parser strings words assocs vocabs ;
IN: vocabs.parser IN: vocabs.parser
ARTICLE: "vocabulary-search-shadow" "Shadowing word names" ARTICLE: "word-search-errors" "Word lookup errors"
"If adding a vocabulary to the search path results in a word in another vocabulary becoming inaccessible due to the new vocabulary defining a word with the same name, we say that the old word has been " { $emphasis "shadowed" } "."
$nl
"Here is an example where shadowing occurs:"
{ $code
"IN: foe"
"USING: sequences io ;"
""
": append"
" \"foe::append calls sequences:append\" print append ;"
""
"IN: fee"
""
": append"
" \"fee::append calls fee:append\" print append ;"
""
"IN: fox"
"USE: foe"
""
": append"
" \"fox::append calls foe:append\" print append ;"
""
"\"1234\" \"5678\" append print"
""
"USE: fox"
"\"1234\" \"5678\" append print"
}
"When placed in a source file and run, the above code produces the following output:"
{ $code
"foe:append calls sequences:append"
"12345678"
"fee:append calls foe:append"
"foe:append calls sequences:append"
"12345678"
} ;
ARTICLE: "vocabulary-search-errors" "Word lookup errors"
"If the parser cannot not find a word in the current vocabulary search path, it attempts to look for the word in all loaded vocabularies." "If the parser cannot not find a word in the current vocabulary search path, it attempts to look for the word in all loaded vocabularies."
$nl $nl
"If " { $link auto-use? } " mode is off, a restartable error is thrown with a restart for each vocabulary in question, together with a restart which defers the word in the current vocabulary, as if " { $link POSTPONE: DEFER: } " was used." "If " { $link auto-use? } " mode is off, a restartable error is thrown with a restart for each vocabulary in question, together with a restart which defers the word in the current vocabulary, as if " { $link POSTPONE: DEFER: } " was used."
@ -47,71 +11,154 @@ $nl
"If any restarts were invoked, or if " { $link auto-use? } " is on, the parser will print the correct " { $link POSTPONE: USING: } " after parsing completes. This form can be copy and pasted back into the source file." "If any restarts were invoked, or if " { $link auto-use? } " is on, the parser will print the correct " { $link POSTPONE: USING: } " after parsing completes. This form can be copy and pasted back into the source file."
{ $subsection auto-use? } ; { $subsection auto-use? } ;
ARTICLE: "vocabulary-search" "Vocabulary search path" ARTICLE: "word-search-syntax" "Syntax to control word lookup"
"When the parser reads a token, it attempts to look up a word named by that token. The lookup is performed by searching each vocabulary in the search path, in order." "Parsing words which make all words in a vocabulary available:"
$nl
"For a source file the vocabulary search path starts off with one vocabulary:"
{ $code "syntax" }
"The " { $vocab-link "syntax" } " vocabulary consists of a set of parsing words for reading Factor data and defining new words."
$nl
"In the listener, the " { $vocab-link "scratchpad" } " is the default vocabulary for new word definitions. However, when loading source files, there is no default vocabulary. Defining words before declaring a vocabulary with " { $link POSTPONE: IN: } " results in an error."
$nl
"At the interactive listener, the default search path contains many more vocabularies. Details on the default search path and parser invocation are found in " { $link "parser" } "."
$nl
"Three parsing words deal with the vocabulary search path:"
{ $subsection POSTPONE: IN: }
{ $subsection POSTPONE: USE: } { $subsection POSTPONE: USE: }
{ $subsection POSTPONE: USING: } { $subsection POSTPONE: USING: }
"There are some additional parsing words give more control over word lookup than is offered by " { $link POSTPONE: USE: } " and " { $link POSTPONE: USING: } ":"
{ $subsection POSTPONE: QUALIFIED: } { $subsection POSTPONE: QUALIFIED: }
{ $subsection POSTPONE: QUALIFIED-WITH: } { $subsection POSTPONE: QUALIFIED-WITH: }
"Parsing words which make a subset of all words in a vocabulary available:"
{ $subsection POSTPONE: FROM: } { $subsection POSTPONE: FROM: }
{ $subsection POSTPONE: EXCLUDE: } { $subsection POSTPONE: EXCLUDE: }
{ $subsection POSTPONE: RENAME: } { $subsection POSTPONE: RENAME: }
"These words are useful when there is no way to avoid using two vocabularies with identical word names in the same source file." "Removing vocabularies from the search path:"
{ $subsection POSTPONE: UNUSE: }
"In the listener, the " { $vocab-link "scratchpad" } " is the default vocabulary for new word definitions. In source files, there is no default vocabulary. Defining words before declaring a vocabulary with " { $link POSTPONE: IN: } " results in an error."
{ $subsection POSTPONE: IN: } ;
ARTICLE: "word-search-semantics" "Resolution of ambiguous word names"
"There is a distinction between parsing words which perform “open” imports versus “closed” imports. An open import introduces all words from a vocabulary as identifiers, except possibly a finite set of exclusions. The " { $link POSTPONE: USE: } ", " { $link POSTPONE: USING: } " and " { $link POSTPONE: EXCLUDE: } " words perform open imports. A closed import only adds a fixed set of identifiers. The " { $link POSTPONE: FROM: } ", " { $link POSTPONE: RENAME: } ", " { $link POSTPONE: QUALIFIED: } " and " { $link POSTPONE: QUALIFIED-WITH: } " words perform closed imports. Note that the latter two are considered as closed imports, due to the fact that all identifiers they introduce are unambiguously qualified with a prefix. The " { $link POSTPONE: IN: } " parsing word also performs a closed import of the newly-created vocabulary."
$nl $nl
"Private words can be defined; note that this is just a convention and they can be called from other vocabularies anyway:" "When the parser encounters a reference to a word, it first searches the closed imports, in order. Closed imports are searched from the most recent to least recent. If the word could not be found this way, it searches open imports. Unlike closed imports, with open imports, the order does not matter -- instead, if more than one vocabulary defines a word with this name, an error is thrown."
{ $subsection ambiguous-use-error }
"To resolve the error, add a closed import, using " { $link POSTPONE: FROM: } ", " { $link POSTPONE: QUALIFIED: } " or " { $link POSTPONE: QUALIFIED-WITH: } ". The closed import will then take precedence over the open imports, and the ambiguity will be resolved."
$nl
"The rationale for this behavior is as follows. Open imports are named such because they are open to future extension; if a future version of a vocabulary that you use adds new words, those new words will now be in scope in your source file, too. To avoid problems, any references to the new word have to be resolved since the parser cannot safely determine which vocabulary was meant. This problem can be avoided entirely by using only closed imports, but this leads to additional verbosity."
$nl
"In practice, a small set of guidelines helps avoid name clashes:"
{ $list
"Keep vocabularies small"
{ "Hide internal words using " { $link POSTPONE: <PRIVATE } }
{ "Make good use of " { $link POSTPONE: FROM: } ", " { $link POSTPONE: QUALIFIED: } " or " { $link POSTPONE: QUALIFIED-WITH: } }
} ;
ARTICLE: "word-search-private" "Private words"
"Words which only serve as implementation detail should be defined in a private code block. Words in a private code blocks get defined in a vocabulary whose name is the name of the current vocabulary suffixed with " { $snippet ".private" } ". Privacy is not enforced by the system; private words can be called from other vocabularies, and from the listener. However, this should be avoided where possible."
{ $subsection POSTPONE: <PRIVATE } { $subsection POSTPONE: <PRIVATE }
{ $subsection POSTPONE: PRIVATE> } { $subsection POSTPONE: PRIVATE> } ;
{ $subsection "vocabulary-search-errors" }
{ $subsection "vocabulary-search-shadow" } ARTICLE: "word-search" "Parse-time word lookup"
"When the parser reads a word name, it resolves the word at parse-time, looking up the " { $link word } " instance in the right vocabulary and adding it to the parse tree."
$nl
"Initially, only words from the " { $vocab-link "syntax" } " vocabulary are available in source files. Since most files will use words in other vocabularies, they will need to make those words available using a set of parsing words."
{ $subsection "word-search-syntax" }
{ $subsection "word-search-private" }
{ $subsection "word-search-semantics" }
{ $subsection "word-search-errors" }
{ $see-also "words" } ; { $see-also "words" } ;
ABOUT: "vocabulary-search" ARTICLE: "word-search-parsing" "Word lookup in parsing words"
"The parsing words described in " { $link "word-search-syntax" } " are implemented using the below words, which you can also call from your own parsing words."
$nl
"The current state used for word search is stored in a " { $emphasis "manifest" } ":"
{ $subsection manifest }
"Words for working with the current manifest:"
{ $subsection use-vocab }
{ $subsection unuse-vocab }
{ $subsection only-use-vocabs }
{ $subsection add-qualified }
{ $subsection add-words-from }
{ $subsection add-words-excluding }
"Words used to implement " { $link POSTPONE: IN: } ":"
{ $subsection current-vocab }
{ $subsection set-current-vocab }
"Words used to implement " { $link "word-search-private" } ":"
{ $subsection begin-private }
{ $subsection end-private } ;
HELP: use ABOUT: "word-search"
{ $var-description "A variable holding the current vocabulary search path as a sequence of assocs." } ;
HELP: in HELP: manifest
{ $var-description "A variable holding the name of the current vocabulary for new definitions." } ; { $var-description "The current manifest. Only set at parse time." }
{ $class-description "Encapsulates the current vocabulary, as well as the vocabulary search path." } ;
HELP: current-vocab HELP: <manifest>
{ $values { "str" "a vocabulary" } } { $values { "manifest" manifest } }
{ $description "Returns the vocabulary stored in the " { $link in } " symbol. Throws an error if the current vocabulary is " { $link f } "." } ; { $description "Creates a new manifest." } ;
HELP: (add-use) HELP: set-current-vocab
{ $values { "vocab" "an assoc mapping strings to words" } }
{ $description "Adds an assoc at the front of the search path." }
$parsing-note ;
HELP: add-use
{ $values { "vocab" string } }
{ $description "Adds a new vocabulary at the front of the search path after loading it if necessary. Subsequent word lookups by the parser will search this vocabulary first." }
$parsing-note
{ $errors "Throws an error if the vocabulary does not exist." } ;
HELP: set-use
{ $values { "seq" "a sequence of strings" } }
{ $description "Sets the vocabulary search path. Later vocabularies take precedence." }
{ $errors "Throws an error if one of the vocabularies does not exist." }
$parsing-note ;
HELP: set-in
{ $values { "name" string } } { $values { "name" string } }
{ $description "Sets the current vocabulary where new words will be defined, creating the vocabulary first if it does not exist." } { $description "Sets the current vocabulary where new words will be defined, creating the vocabulary first if it does not exist." }
$parsing-note ; { $notes "This word is used to implement " { $link POSTPONE: IN: } "." } ;
HELP: no-current-vocab
{ $error-description "Thrown when a new word is defined in a source file that does not have an " { $link POSTPONE: IN: } " form." } ;
HELP: current-vocab
{ $values { "vocab" vocab } }
{ $description "Returns the current vocabulary, where new words will be defined." }
{ $errors "Throws an error if the current vocabulary has not been set." } ;
HELP: begin-private
{ $description "Begins a block of private word definitions. Private word definitions are placed in the current vocabulary name, suffixed with " { $snippet ".private" } "." }
{ $notes "This word is used to implement " { $link POSTPONE: <PRIVATE } "." } ;
HELP: end-private
{ $description "Ends a block of private word definitions." }
{ $notes "This word is used to implement " { $link POSTPONE: PRIVATE> } "." } ;
HELP: use-vocab
{ $values { "vocab" "a vocabulary specifier" } }
{ $description "Adds a vocabulary to the current manifest." }
{ $notes "This word is used to implement " { $link POSTPONE: USE: } "." } ;
HELP: unuse-vocab
{ $values { "vocab" "a vocabulary specifier" } }
{ $description "Removes a vocabulary from the current manifest." }
{ $notes "This word is used to implement " { $link POSTPONE: UNUSE: } "." } ;
HELP: only-use-vocabs
{ $values { "vocabs" "a sequence of vocabulary specifiers" } }
{ $description "Replaces the current manifest's vocabulary search path with the given set of vocabularies." } ;
HELP: add-qualified
{ $values { "vocab" "a vocabulary specifier" } { "prefix" string } }
{ $description "Adds the vocabulary's words, prefixed with the given string, to the current manifest." }
{ $notes "If adding the vocabulary introduces ambiguity, the vocabulary will take precedence when resolving any ambiguous names. See the example in " { $link POSTPONE: QUALIFIED: } " for further explanation." } ;
HELP: add-words-from
{ $values { "vocab" "a vocabulary specifier" } { "words" "a sequence of word names" } }
{ $description "Adds " { $snippet "words" } " from " { $snippet "vocab" } " to the current manifest." }
{ $notes "This word is used to implement " { $link POSTPONE: FROM: } "." } ;
HELP: add-words-excluding
{ $values { "vocab" "a vocabulary specifier" } { "words" "a sequence of word names" } }
{ $description "Adds all words except for " { $snippet "words" } " from " { $snippet "vocab" } " to the manifest." }
{ $notes "This word is used to implement " { $link POSTPONE: EXCLUDE: } "." } ;
HELP: add-renamed-word
{ $values { "word" string } { "vocab" "a vocabulary specifier" } { "new-name" string } }
{ $description "Imports " { $snippet "word" } " from " { $snippet "vocab" } ", but renamed to " { $snippet "new-name" } "." }
{ $notes "This word is used to implement " { $link POSTPONE: RENAME: } "." } ;
HELP: use-words
{ $values { "assoc" assoc } }
{ $description "Adds an assoc mapping word names to words to the current manifest." }
{ $notes "This word is used by " { $link "locals" } " to implement lexically-scoped names." } ;
HELP: unuse-words
{ $values { "assoc" assoc } }
{ $description "Removes an assoc mapping word names to words from the current manifest." }
{ $notes "This word is used by " { $link "locals" } " to implement lexically-scoped names." } ;
HELP: ambiguous-use-error
{ $error-description "Thrown when a word name referenced in source file is available in more than one vocabulary in the manifest. Such cases must be explicitly disambiguated using " { $link POSTPONE: FROM: } ", " { $link POSTPONE: EXCLUDE: } ", " { $link POSTPONE: QUALIFIED: } ", or " { $link POSTPONE: QUALIFIED-WITH: } "." } ;
HELP: search-manifest
{ $values { "name" string } { "manifest" manifest } { "word/f" { $maybe word } } }
{ $description "Searches for a word by name in the given manifest. If no such word could be found, outputs " { $link f } "." } ;
HELP: search HELP: search
{ $values { "str" string } { "word/f" { $maybe word } } } { $values { "name" string } { "word/f" { $maybe word } } }
{ $description "Searches for a word by name in the current vocabulary search path. If no such word could be found, outputs " { $link f } "." } { $description "Searches for a word by name in the current manifest. If no such word could be found, outputs " { $link f } "." }
$parsing-note ; $parsing-note ;

View File

@ -32,8 +32,7 @@ M: manifest clone
manifest get manifest get
[ search-vocabs>> delete-all ] [ search-vocabs>> delete-all ]
[ qualified-vocabs>> delete-all ] [ qualified-vocabs>> delete-all ]
[ extra-words>> delete-all ] bi ;
tri ;
: (use-vocab) ( vocab -- vocab seq ) : (use-vocab) ( vocab -- vocab seq )
load-vocab manifest get search-vocabs>> ; load-vocab manifest get search-vocabs>> ;
@ -44,22 +43,25 @@ M: manifest clone
: (from) ( vocab words -- vocab words words' assoc ) : (from) ( vocab words -- vocab words words' assoc )
2dup swap load-vocab words>> ; 2dup swap load-vocab words>> ;
: (use-words) ( assoc -- assoc seq )
manifest get extra-words>> ;
: extract-words ( seq assoc -- assoc' ) : extract-words ( seq assoc -- assoc' )
extract-keys dup [ [ drop ] [ no-word-error ] if ] assoc-each ; extract-keys dup [ [ drop ] [ no-word-error ] if ] assoc-each ;
: (lookup) ( name assoc -- word/f ) : (lookup) ( name assoc -- word/f )
at dup forward-reference? [ drop f ] when ; at dup forward-reference? [ drop f ] when ;
TUPLE: extra-words words ;
C: <extra-words> extra-words
: (use-words) ( assoc -- extra-words seq )
<extra-words> manifest get qualified-vocabs>> ;
PRIVATE> PRIVATE>
: set-current-vocab ( name -- ) : set-current-vocab ( name -- )
create-vocab manifest get create-vocab
[ (>>current-vocab) ] [ manifest get (>>current-vocab) ]
[ [ words>> ] dip extra-words>> push ] [ words>> <extra-words> (add-qualified) ] bi ;
2bi ;
TUPLE: no-current-vocab ; TUPLE: no-current-vocab ;
@ -124,9 +126,9 @@ TUPLE: rename word vocab words ;
: add-renamed-word ( word vocab new-name -- ) : add-renamed-word ( word vocab new-name -- )
<rename> (add-qualified) ; <rename> (add-qualified) ;
: use-words ( words -- ) (use-words) push ; : use-words ( assoc -- ) (use-words) push ;
: unuse-words ( words -- ) (use-words) delq ; : unuse-words ( assoc -- ) (use-words) delq ;
ERROR: ambiguous-use-error words ; ERROR: ambiguous-use-error words ;
@ -148,17 +150,10 @@ ERROR: ambiguous-use-error words ;
qualified-vocabs>> qualified-vocabs>>
(vocab-search) 0 = [ drop f ] [ peek ] if ; (vocab-search) 0 = [ drop f ] [ peek ] if ;
: word-search ( name manifest -- word/f )
extra-words>> [ (lookup) ] with map-find-last drop ;
PRIVATE> PRIVATE>
: search-manifest ( name manifest -- word/f ) : search-manifest ( name manifest -- word/f )
2dup word-search dup [ 2nip ] [ 2dup qualified-search dup [ 2nip ] [ drop vocab-search ] if ;
drop 2dup qualified-search dup [ 2nip ] [
drop vocab-search
] if
] if ;
: search ( name -- word/f ) : search ( name -- word/f )
manifest get search-manifest ; manifest get search-manifest ;

View File

@ -8,7 +8,7 @@ ARTICLE: "interned-words" "Looking up and creating words"
$nl $nl
"Words whose names are known at parse time -- that is, most words making up your program -- can be referenced in source code by stating their name. However, the parser itself, and sometimes code you write, will need to create look up words dynamically." "Words whose names are known at parse time -- that is, most words making up your program -- can be referenced in source code by stating their name. However, the parser itself, and sometimes code you write, will need to create look up words dynamically."
$nl $nl
"Parsing words add definitions to the current vocabulary. When a source file is being parsed, the current vocabulary is initially set to " { $vocab-link "scratchpad" } ". The current vocabulary may be changed with the " { $link POSTPONE: IN: } " parsing word (see " { $link "vocabulary-search" } ")." "Parsing words add definitions to the current vocabulary. When a source file is being parsed, the current vocabulary is initially set to " { $vocab-link "scratchpad" } ". The current vocabulary may be changed with the " { $link POSTPONE: IN: } " parsing word (see " { $link "word-search" } ")."
{ $subsection create } { $subsection create }
{ $subsection create-in } { $subsection create-in }
{ $subsection lookup } ; { $subsection lookup } ;

View File

@ -1,5 +1,6 @@
USING: accessors arrays bank calendar kernel math math.functions USING: accessors arrays bank calendar kernel math math.functions
namespaces make tools.test tools.walker ; namespaces make tools.test tools.walker ;
FROM: bank => balance>> ;
IN: bank.tests IN: bank.tests
SYMBOL: my-account SYMBOL: my-account

View File

@ -36,10 +36,8 @@ MEMO: (vocab-words) ( name -- seq )
: current-words ( -- seq ) : current-words ( -- seq )
manifest get manifest get
[ search-vocabs>> [ words>> ] map ] [ search-vocabs>> ] [ qualified-vocabs>> ] bi [ words>> ] bi@
[ qualified-vocabs>> [ words>> ] map ] assoc-union keys ; inline
[ extra-words>> ]
tri 3append assoc-combine keys ; inline
: vocabs-words ( names -- seq ) : vocabs-words ( names -- seq )
prune [ (vocab-words) ] map concat ; inline prune [ (vocab-words) ] map concat ; inline

View File

@ -54,7 +54,7 @@ $nl
} }
"The standard precedence rules apply: Grouping with parentheses before " { $snippet "*" } ", " { $snippet "/" } "and " { $snippet "%" } " before " { $snippet "+" } " and " { $snippet "-" } "." "The standard precedence rules apply: Grouping with parentheses before " { $snippet "*" } ", " { $snippet "/" } "and " { $snippet "%" } " before " { $snippet "+" } " and " { $snippet "-" } "."
{ $example { $example
"USING: infix prettyprint ;" "USE: infix"
"[infix 5-40/10*2 infix] ." "[infix 5-40/10*2 infix] ."
"-3" "-3"
} }
@ -65,7 +65,7 @@ $nl
"The word name must consist of the letters a-z, A-Z, _ or 0-9, and the first character can't be a number." "The word name must consist of the letters a-z, A-Z, _ or 0-9, and the first character can't be a number."
} }
{ $example { $example
"USING: infix locals math math.functions prettyprint ;" "USING: infix locals math.functions ;"
":: binary_entropy ( p -- h )" ":: binary_entropy ( p -- h )"
" [infix -(p*log(p) + (1-p)*log(1-p)) / log(2) infix] ;" " [infix -(p*log(p) + (1-p)*log(1-p)) / log(2) infix] ;"
"[infix binary_entropy( sqrt(0.25) ) infix] ." "[infix binary_entropy( sqrt(0.25) ) infix] ."
@ -74,13 +74,13 @@ $nl
$nl $nl
"You can access " { $vocab-link "sequences" } " inside infix expressions with the familiar " { $snippet "arr[index]" } " notation." "You can access " { $vocab-link "sequences" } " inside infix expressions with the familiar " { $snippet "arr[index]" } " notation."
{ $example { $example
"USING: arrays infix prettyprint ;" "USING: arrays infix ;"
"[infix| myarr [ { 1 2 3 4 } ] | myarr[4/2]*3 infix] ." "[infix| myarr [ { 1 2 3 4 } ] | myarr[4/2]*3 infix] ."
"9" "9"
} }
"Please note: in Factor " { $emphasis "fixnums are sequences too." } " If you are not careful with sequence accesses you may introduce subtle bugs:" "Please note: in Factor " { $emphasis "fixnums are sequences too." } " If you are not careful with sequence accesses you may introduce subtle bugs:"
{ $example { $example
"USING: arrays infix locals prettyprint ;" "USING: arrays infix locals ;"
":: add-2nd-element ( x y -- res )" ":: add-2nd-element ( x y -- res )"
" [infix x[1] + y[1] infix] ;" " [infix x[1] + y[1] infix] ;"
"{ 1 2 3 } 5 add-2nd-element ." "{ 1 2 3 } 5 add-2nd-element ."

View File

@ -1,7 +1,7 @@
! Copyright (C) 2008 Doug Coleman. ! Copyright (C) 2008 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: tools.test math.floating-point math.constants kernel USING: tools.test math.floating-point kernel
math.constants fry sequences kernel math ; math.constants fry sequences math ;
IN: math.floating-point.tests IN: math.floating-point.tests
[ t ] [ pi >double< >double pi = ] unit-test [ t ] [ pi >double< >double pi = ] unit-test

View File

@ -1,4 +1,5 @@
USING: tools.test math kernel sequences lists promises monads ; USING: tools.test math kernel sequences lists promises monads ;
FROM: monads => do ;
IN: monads.tests IN: monads.tests
[ 5 ] [ 1 identity-monad return [ 4 + ] fmap run-identity ] unit-test [ 5 ] [ 1 identity-monad return [ 4 + ] fmap run-identity ] unit-test

View File

@ -1,6 +1,7 @@
! (c)2009 Joe Groff bsd license ! (c)2009 Joe Groff bsd license
USING: accessors classes.tuple compiler.units kernel qw roles sequences USING: accessors classes.tuple compiler.units kernel qw roles sequences
tools.test ; tools.test ;
FROM: roles => TUPLE: ;
IN: roles.tests IN: roles.tests
ROLE: fork tines ; ROLE: fork tines ;

View File

@ -1,5 +1,6 @@
USING: accessors kernel tetris.game tetris.board tetris.piece tools.test USING: accessors kernel tetris.game tetris.board tetris.piece tools.test
sequences ; sequences ;
FROM: tetris.game => level>> ;
[ t ] [ <default-tetris> [ current-piece ] [ next-piece ] bi and t f ? ] unit-test [ t ] [ <default-tetris> [ current-piece ] [ next-piece ] bi and t f ? ] unit-test
[ t ] [ <default-tetris> { 1 1 } can-move? ] unit-test [ t ] [ <default-tetris> { 1 1 } can-move? ] unit-test