Update documentation for stricter vocabulary search path semantics
parent
79f5c30a7a
commit
66a9416473
|
@ -30,8 +30,8 @@ ARTICLE: "checksums.openssl" "OpenSSL checksums"
|
|||
"An error thrown if the digest name is unrecognized:"
|
||||
{ $subsection unknown-digest }
|
||||
"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:"
|
||||
{ $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"
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
USING: alien alien.c-types alien.syntax compiler kernel
|
||||
namespaces namespaces tools.test sequences stack-checker
|
||||
stack-checker.errors words arrays parser quotations
|
||||
continuations effects namespaces.private io io.streams.string
|
||||
memory system threads tools.test math accessors combinators
|
||||
specialized-arrays.float alien.libraries io.pathnames
|
||||
USING: alien alien.c-types alien.syntax compiler kernel namespaces
|
||||
sequences stack-checker stack-checker.errors words arrays parser
|
||||
quotations continuations effects namespaces.private io
|
||||
io.streams.string memory system threads tools.test math accessors
|
||||
combinators specialized-arrays.float alien.libraries io.pathnames
|
||||
io.backend ;
|
||||
IN: compiler.tests.alien
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
USING: generalizations accessors arrays compiler kernel
|
||||
kernel.private math hashtables.private math.private namespaces
|
||||
sequences sequences.private tools.test namespaces.private
|
||||
slots.private sequences.private byte-arrays alien
|
||||
USING: generalizations accessors arrays compiler kernel kernel.private
|
||||
math hashtables.private math.private namespaces sequences tools.test
|
||||
namespaces.private slots.private sequences.private byte-arrays alien
|
||||
alien.accessors layouts words definitions compiler.units io
|
||||
combinators vectors grouping make ;
|
||||
QUALIFIED: namespaces.private
|
||||
IN: compiler.tests.codegen
|
||||
|
||||
! Originally, this file did black box testing of templating
|
||||
|
@ -48,7 +48,7 @@ unit-test
|
|||
[ 3 ]
|
||||
[
|
||||
global [ 3 \ foo set ] bind
|
||||
\ foo [ global >n get ndrop ] compile-call
|
||||
\ foo [ global >n get namespaces.private:ndrop ] compile-call
|
||||
] unit-test
|
||||
|
||||
: blech ( x -- ) drop ;
|
||||
|
@ -62,7 +62,7 @@ unit-test
|
|||
[ 3 ]
|
||||
[
|
||||
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
|
||||
|
||||
[ 3 ]
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
USING: accessors arrays compiler.units kernel kernel.private math
|
||||
math.constants math.private sequences strings tools.test words
|
||||
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
|
||||
alien.accessors alien.c-types alien.syntax alien.strings
|
||||
namespaces libc sequences.private io.encodings.ascii
|
||||
namespaces libc io.encodings.ascii
|
||||
classes compiler ;
|
||||
IN: compiler.tests.intrinsics
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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
|
||||
|
||||
[ f ] [ 0.0 -0.0 eql? ] unit-test
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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.normalization compiler.tree.propagation
|
||||
compiler.tree.cleanup compiler.tree.escape-analysis
|
||||
|
|
|
@ -3,6 +3,7 @@ USING: tools.test concurrency.distributed kernel io.files
|
|||
io.files.temp io.directories arrays io.sockets system
|
||||
combinators threads math sequences concurrency.messaging
|
||||
continuations accessors prettyprint ;
|
||||
FROM: concurrency.messaging => receive send ;
|
||||
|
||||
: test-node ( -- addrspec )
|
||||
{
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
IN: concurrency.exchangers.tests
|
||||
USING: sequences tools.test concurrency.exchangers
|
||||
USING: tools.test concurrency.exchangers
|
||||
concurrency.count-downs concurrency.promises locals kernel
|
||||
threads ;
|
||||
FROM: sequences => 3append ;
|
||||
|
||||
:: exchanger-test ( -- string )
|
||||
[let |
|
||||
|
|
|
@ -53,7 +53,7 @@ ARTICLE: { "concurrency" "synchronous-sends" } "Synchronous sends"
|
|||
{ $subsection reply-synchronous }
|
||||
"An example:"
|
||||
{ $example
|
||||
"USING: concurrency.messaging kernel prettyprint threads ;"
|
||||
"USING: concurrency.messaging threads ;"
|
||||
"IN: scratchpad"
|
||||
": pong-server ( -- )"
|
||||
" receive [ \"pong\" ] dip reply-synchronous ;"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
IN: cpu.ppc.assembler.tests
|
||||
USING: cpu.ppc.assembler tools.test arrays kernel namespaces
|
||||
make vocabs sequences ;
|
||||
FROM: cpu.ppc.assembler => B ;
|
||||
|
||||
: test-assembler ( expected quot -- )
|
||||
[ 1array ] [ [ B{ } make ] curry ] bi* unit-test ;
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
! Copyright (C) 2008 Doug Coleman.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
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
|
||||
db.postgresql accessors random math.bitwise system
|
||||
math.ranges strings urls fry db.tuples.private db.private
|
||||
db.tester ;
|
||||
FROM: math.ranges => [a,b] ;
|
||||
IN: db.tuples.tests
|
||||
|
||||
TUPLE: person the-id the-name the-number the-real
|
||||
|
|
|
@ -2,6 +2,7 @@ USING: calendar ftp.server io.encodings.ascii io.files
|
|||
io.files.unique namespaces threads tools.test kernel
|
||||
io.servers.connection ftp.client accessors urls
|
||||
io.pathnames io.directories sequences fry ;
|
||||
FROM: ftp.client => ftp-get ;
|
||||
IN: ftp.server.tests
|
||||
|
||||
: test-file-contents ( -- string )
|
||||
|
|
|
@ -136,7 +136,7 @@ ARTICLE: "cookbook-variables" "Dynamic variables 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
|
||||
"For example, a source file containing the following code will print a parse error if you try loading it:"
|
||||
{ $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."
|
||||
{ $references
|
||||
{ }
|
||||
"vocabulary-search"
|
||||
"word-search"
|
||||
"words"
|
||||
"parser"
|
||||
} ;
|
||||
|
@ -286,7 +286,6 @@ ARTICLE: "cookbook-pitfalls" "Pitfalls to avoid"
|
|||
{ $list
|
||||
"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."
|
||||
{ "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" } "." }
|
||||
{ "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." }
|
||||
|
|
|
@ -248,14 +248,14 @@ ARTICLE: "handbook-language-reference" "The language"
|
|||
{ $subsection "namespaces-global" }
|
||||
{ $subsection "values" }
|
||||
{ $heading "Abstractions" }
|
||||
{ $subsection "errors" }
|
||||
{ $subsection "fry" }
|
||||
{ $subsection "objects" }
|
||||
{ $subsection "errors" }
|
||||
{ $subsection "destructors" }
|
||||
{ $subsection "continuations" }
|
||||
{ $subsection "memoize" }
|
||||
{ $subsection "parsing-words" }
|
||||
{ $subsection "macros" }
|
||||
{ $subsection "fry" }
|
||||
{ $subsection "continuations" }
|
||||
{ $heading "Program organization" }
|
||||
{ $subsection "vocabs.loader" }
|
||||
"Vocabularies tagged " { $link T{ vocab-tag { name "extensions" } } } " implement various additional language abstractions." ;
|
||||
|
|
|
@ -38,7 +38,7 @@ $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."
|
||||
$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
|
||||
"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
|
||||
|
|
|
@ -3,6 +3,7 @@ USING: tools.test kernel io.streams.string
|
|||
io.streams.null accessors inspector html.streams
|
||||
html.components html.forms namespaces
|
||||
xml.writer ;
|
||||
FROM: html.components => inspector ;
|
||||
|
||||
[ ] [ begin-form ] unit-test
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
IN: html.forms.tests
|
||||
USING: kernel sequences tools.test assocs html.forms validators accessors
|
||||
namespaces ;
|
||||
FROM: html.forms => values ;
|
||||
|
||||
: with-validation ( quot -- messages )
|
||||
[
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
USING: html.streams html.streams.private accessors io
|
||||
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 ;
|
||||
IN: html.streams.tests
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
USING: html.templates html.templates.chloe
|
||||
tools.test io.streams.string kernel sequences ascii boxes
|
||||
namespaces xml html.components html.forms
|
||||
splitting unicode.categories furnace accessors
|
||||
splitting furnace accessors
|
||||
html.templates.chloe.compiler ;
|
||||
IN: html.templates.chloe.tests
|
||||
|
||||
|
|
|
@ -173,10 +173,10 @@ Set-Cookie: oo="bar; a=b"; comment="your mom"; httponly=yes
|
|||
] unit-test
|
||||
|
||||
! Live-fire exercise
|
||||
USING: http.server http.server.static furnace.sessions furnace.alloy
|
||||
furnace.actions furnace.auth furnace.auth.login furnace.db http.client
|
||||
io.servers.connection io.files io.files.temp io.directories io io.encodings.ascii
|
||||
accessors namespaces threads
|
||||
USING: http.server.static furnace.sessions furnace.alloy
|
||||
furnace.actions furnace.auth furnace.auth.login furnace.db
|
||||
io.servers.connection io.files io.files.temp io.directories io
|
||||
threads
|
||||
http.server.responses http.server.redirection furnace.redirection
|
||||
http.server.dispatchers db.tuples ;
|
||||
|
||||
|
|
|
@ -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
|
||||
sequences io.files.temp ;
|
||||
IN: io.files.info.tests
|
||||
|
|
|
@ -15,8 +15,6 @@ SYNTAX: hello "Hi" print ;
|
|||
] with-file-vocabs
|
||||
|
||||
[
|
||||
"debugger" add-ambiguous-use
|
||||
|
||||
[ [ \ + 1 2 3 4 ] ]
|
||||
[
|
||||
[
|
||||
|
|
|
@ -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
|
||||
|
||||
[ { 1 3 5 7 } ] [ 4 odds ltake list>array ] unit-test
|
||||
|
|
|
@ -93,22 +93,12 @@ HELP: luntil
|
|||
{ $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." } ;
|
||||
|
||||
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
|
||||
{ $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." } ;
|
||||
|
||||
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." } ;
|
||||
|
||||
HELP: lfrom
|
||||
|
@ -117,7 +107,7 @@ HELP: lfrom
|
|||
|
||||
HELP: seq>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 } ;
|
||||
|
||||
HELP: >list
|
||||
|
@ -154,7 +144,7 @@ HELP: lmerge
|
|||
{ $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." }
|
||||
{ $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
|
||||
|
|
|
@ -178,12 +178,6 @@ M: lazy-filter nil? ( lazy-filter -- bool )
|
|||
] if
|
||||
] if ;
|
||||
|
||||
: list>vector ( list -- vector )
|
||||
[ [ , ] leach ] V{ } make ;
|
||||
|
||||
: list>array ( list -- array )
|
||||
[ [ , ] leach ] { } make ;
|
||||
|
||||
TUPLE: lazy-append list1 list2 ;
|
||||
|
||||
C: <lazy-append> lazy-append
|
||||
|
|
|
@ -54,21 +54,21 @@ ARTICLE: { "lists" "manipulation" } "Manipulating lists"
|
|||
{ $subsection lcut } ;
|
||||
|
||||
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." } ;
|
||||
|
||||
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." } ;
|
||||
|
||||
{ cons swons uncons unswons } related-words
|
||||
|
||||
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." } ;
|
||||
|
||||
HELP: cdr
|
||||
{ $values { "cons" "a cons object" } { "cdr" "a cons object" } }
|
||||
{ $values { "cons" list } { "cdr" list } }
|
||||
{ $description "Returns the tail of the list." } ;
|
||||
|
||||
{ car cdr } related-words
|
||||
|
@ -86,51 +86,51 @@ HELP: nil?
|
|||
{ 1list 2list 3list } related-words
|
||||
|
||||
HELP: 1list
|
||||
{ $values { "obj" "an object" } { "cons" "a cons object" } }
|
||||
{ $values { "obj" "an object" } { "cons" list } }
|
||||
{ $description "Create a list with 1 element." } ;
|
||||
|
||||
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." } ;
|
||||
|
||||
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." } ;
|
||||
|
||||
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." }
|
||||
{ $see-also llength cons car cdr } ;
|
||||
|
||||
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." }
|
||||
{ $see-also lnth cons car cdr } ;
|
||||
|
||||
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." } ;
|
||||
|
||||
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." } ;
|
||||
|
||||
{ leach foldl lmap>array } related-words
|
||||
|
||||
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." } ;
|
||||
|
||||
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." } ;
|
||||
|
||||
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." } ;
|
||||
|
||||
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." } ;
|
||||
|
||||
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." } ;
|
||||
|
||||
HELP: list>array
|
||||
{ $values { "list" "a cons object" } { "array" array } }
|
||||
{ $description "Turns the given cons object into an array, maintaing order." } ;
|
||||
|
||||
HELP: sequence>cons
|
||||
{ $values { "sequence" sequence } { "list" cons } }
|
||||
{ $description "Turns the given array into a cons object, maintaing order." } ;
|
||||
{ $values { "list" list } { "array" array } }
|
||||
{ $description "Convert a list into an array." } ;
|
||||
|
||||
HELP: deep-list>array
|
||||
{ $values { "list" list } { "array" array } }
|
||||
{ $description "Recursively turns the given cons object into an array, maintaing 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." } ;
|
||||
{ $description "Recursively turns the given cons object into an array, maintaining order and also converting nested lists." } ;
|
||||
|
||||
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" } }
|
||||
{ $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." } ;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
! Copyright (C) 2008 James Cash
|
||||
! 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
|
||||
|
||||
{ { 3 4 5 6 7 } } [
|
||||
|
@ -23,49 +23,24 @@ IN: lists.tests
|
|||
+nil+ } } } } 0 [ + ] foldl
|
||||
] 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+ } } } } } [
|
||||
{ 1 2 3 4 } sequence>cons [ 1+ ] lmap
|
||||
{ 1 2 3 4 } seq>list [ 1+ ] lmap
|
||||
] unit-test
|
||||
|
||||
{ 15 } [
|
||||
{ 1 2 3 4 5 } sequence>cons 0 [ + ] foldr
|
||||
{ 1 2 3 4 5 } seq>list 0 [ + ] foldr
|
||||
] unit-test
|
||||
|
||||
{ { 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
|
||||
|
||||
{ 5 } [
|
||||
{ 1 2 3 4 5 } sequence>cons llength
|
||||
] unit-test
|
||||
|
||||
{ { 3 4 { 5 6 { 7 } } } } [
|
||||
{ 1 2 { 3 4 { 5 } } } deep-sequence>cons [ atom? ] [ 2 + ] traverse deep-list>array
|
||||
{ 1 2 3 4 5 } seq>list llength
|
||||
] unit-test
|
||||
|
||||
{ { 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
|
||||
|
||||
[ { 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
|
||||
|
|
|
@ -65,7 +65,7 @@ ${ five six 7 } .
|
|||
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."
|
||||
{ $example <"
|
||||
USING: kernel literals math prettyprint ;
|
||||
USE: literals
|
||||
IN: scratchpad
|
||||
|
||||
CONSTANT: five 5
|
||||
|
|
|
@ -4,9 +4,9 @@ IN: math.complex
|
|||
|
||||
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:"
|
||||
{ $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:"
|
||||
{ $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." ;
|
||||
|
||||
ARTICLE: "complex-numbers" "Complex numbers"
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
! Copyright (C) 2009 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: tools.test opengl.textures opengl.textures.private
|
||||
opengl.textures.private images kernel namespaces accessors
|
||||
sequences ;
|
||||
images kernel namespaces accessors sequences ;
|
||||
IN: opengl.textures.tests
|
||||
|
||||
[
|
||||
|
|
|
@ -461,7 +461,7 @@ M: ebnf-sequence build-locals ( code ast -- code )
|
|||
|
||||
M: ebnf-var build-locals ( code ast -- )
|
||||
[
|
||||
"FROM: locals => [let* ; FROM: kernel => dup ; [let* | " %
|
||||
"FROM: locals => [let* ; FROM: kernel => dup nip ; [let* | " %
|
||||
name>> % " [ dup ] " %
|
||||
" | " %
|
||||
%
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
! See http://factorcode.org/license.txt for BSD license.
|
||||
!
|
||||
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
|
||||
|
||||
[ ] [ reset-pegs ] unit-test
|
||||
|
|
|
@ -91,15 +91,13 @@ unit-test
|
|||
|
||||
: check-see ( expect name -- ? )
|
||||
[
|
||||
use [ clone ] change
|
||||
|
||||
[
|
||||
[ parse-fresh drop ] with-compilation-unit
|
||||
[
|
||||
"prettyprint.tests" lookup see
|
||||
] with-string-writer "\n" split but-last
|
||||
] keep =
|
||||
] with-scope ;
|
||||
] with-interactive-vocabs ;
|
||||
|
||||
GENERIC: method-layout ( a -- b )
|
||||
|
||||
|
|
|
@ -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:"
|
||||
{ $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:"
|
||||
{ $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." ;
|
||||
|
||||
ARTICLE: { "regexp" "construction" } "Constructing regular expressions"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
! Copyright (C) 2006 Chris Double.
|
||||
! 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
|
||||
sequences math prettyprint parser classes math.constants
|
||||
io.encodings.binary random assocs serialize.private ;
|
||||
|
|
|
@ -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
|
||||
|
||||
[ t ] [ \ + (( a b -- c )) execute-effect-unsafe? ] unit-test
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
IN: struct-arrays.tests
|
||||
USING: struct-arrays tools.test kernel math sequences
|
||||
alien.syntax alien.c-types destructors libc accessors
|
||||
destructors ;
|
||||
alien.syntax alien.c-types destructors libc accessors ;
|
||||
|
||||
C-STRUCT: test-struct
|
||||
{ "int" "x" }
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
USING: accessors ui.gadgets ui.gadgets.private ui.gadgets.packs
|
||||
ui.gadgets.worlds tools.test namespaces models kernel dlists deques
|
||||
math sets math.parser ui sequences hashtables assocs io arrays
|
||||
prettyprint io.streams.string math.rectangles ui.gadgets.private
|
||||
sets generic ;
|
||||
USING: accessors ui.gadgets ui.gadgets.packs ui.gadgets.worlds
|
||||
tools.test namespaces models kernel dlists deques math
|
||||
math.parser ui sequences hashtables assocs io arrays prettyprint
|
||||
io.streams.string math.rectangles ui.gadgets.private sets generic ;
|
||||
IN: ui.gadgets.tests
|
||||
|
||||
[ { 300 300 } ]
|
||||
|
|
|
@ -2,7 +2,7 @@ USING: continuations documents
|
|||
ui.tools.listener hashtables kernel namespaces parser sequences
|
||||
tools.test ui.commands ui.gadgets ui.gadgets.editors
|
||||
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 ;
|
||||
IN: ui.tools.listener.tests
|
||||
|
||||
|
@ -146,7 +146,7 @@ CONSTANT: text "Hello world.\nThis is a test."
|
|||
[ ] [ "listener" get com-end ] unit-test
|
||||
] with-grafted-gadget
|
||||
|
||||
[ ] [ \ + <interactor> vocabs>> use-if-necessary ] unit-test
|
||||
[ ] [ \ + <interactor> manifest>> use-if-necessary ] unit-test
|
||||
|
||||
[ ] [ <listener-gadget> "l" set ] unit-test
|
||||
[ ] [ "l" get com-scroll-up ] unit-test
|
||||
|
|
|
@ -50,7 +50,7 @@ ARTICLE: { "xml.syntax" "interpolation" } "XML interpolation syntax"
|
|||
$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:"
|
||||
{ $example
|
||||
{" USING: splitting sequences xml.writer xml.syntax ;
|
||||
{" USING: splitting xml.writer xml.syntax ;
|
||||
"one two three" " " split
|
||||
[ [XML <item><-></item> XML] ] map
|
||||
<XML <doc><-></doc> XML> pprint-xml"}
|
||||
|
@ -86,7 +86,7 @@ $nl
|
|||
{" <?xml version="1.0" encoding="UTF-8"?>
|
||||
<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:"
|
||||
{ $example {" USING: sequences xml.syntax inverse ;
|
||||
{ $example {" USING: xml.syntax inverse ;
|
||||
: dispatch ( xml -- string )
|
||||
{
|
||||
{ [ [XML <a><-></a> XML] ] [ "a" prepend ] }
|
||||
|
|
|
@ -100,8 +100,6 @@ XML-NS: foo http://blah.com
|
|||
|
||||
[ "" ] [ [XML XML] concat ] unit-test
|
||||
|
||||
USE: inverse
|
||||
|
||||
[ "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" "baz" ] [ [XML <a bar='foo'>baz</a> XML] [ [XML <a bar=<->><-></a> XML] ] undo ] unit-test
|
||||
|
|
|
@ -21,7 +21,7 @@ ARTICLE: "enums" "Enumerations"
|
|||
{ $subsection enum }
|
||||
{ $subsection <enum> }
|
||||
"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
|
||||
{ $class-description "An associative structure which wraps a sequence and maps integers to the corresponding elements of the sequence."
|
||||
|
|
|
@ -51,6 +51,7 @@ IN: bootstrap.syntax
|
|||
"UNION:"
|
||||
"INTERSECTION:"
|
||||
"USE:"
|
||||
"UNUSE:"
|
||||
"USING:"
|
||||
"QUALIFIED:"
|
||||
"QUALIFIED-WITH:"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
USING: alien arrays definitions generic assocs hashtables io
|
||||
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
|
||||
vectors definitions source-files compiler.units growable
|
||||
random stack-checker effects kernel.private sbufs math.order
|
||||
|
|
|
@ -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
|
||||
sequences strings tools.test vectors words quotations classes
|
||||
classes.private classes.union classes.mixin classes.predicate
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
USING: alien arrays definitions generic assocs hashtables io
|
||||
kernel math namespaces parser prettyprint sequences strings
|
||||
tools.test vectors words quotations classes
|
||||
classes.private classes.union classes.mixin classes.predicate
|
||||
classes.algebra vectors definitions source-files
|
||||
compiler.units kernel.private sorting vocabs eval ;
|
||||
USING: alien arrays definitions generic assocs hashtables io kernel
|
||||
math namespaces parser prettyprint sequences strings tools.test words
|
||||
quotations classes classes.private classes.union classes.mixin
|
||||
classes.predicate classes.algebra vectors source-files compiler.units
|
||||
kernel.private sorting vocabs eval ;
|
||||
IN: classes.mixin.tests
|
||||
|
||||
! Test mixins
|
||||
|
|
|
@ -29,6 +29,6 @@ PREDICATE: tuple-c < tuple-b slot>> ;
|
|||
|
||||
GENERIC: ptest ( tuple -- )
|
||||
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
|
||||
|
|
|
@ -152,7 +152,6 @@ ARTICLE: "compositional-examples" "Examples of compositional combinator usage"
|
|||
{ $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 } ":"
|
||||
{ $example
|
||||
"USING: kernel math prettyprint sequences ;"
|
||||
": subtract-n ( seq n -- seq' ) [ - ] curry map ;"
|
||||
"{ 10 20 30 } 5 subtract-n ."
|
||||
"{ 5 15 25 }"
|
||||
|
@ -163,7 +162,6 @@ $nl
|
|||
{ $code ": n-subtract ( n seq -- seq' ) swap [ swap - ] curry map ;" }
|
||||
"Since this pattern comes up often, " { $link with } " encapsulates it:"
|
||||
{ $example
|
||||
"USING: kernel math prettyprint sequences ;"
|
||||
": n-subtract ( n seq -- seq' ) [ - ] with map ;"
|
||||
"30 { 10 20 30 } n-subtract ."
|
||||
"{ 20 10 0 }"
|
||||
|
|
|
@ -48,7 +48,7 @@ $nl
|
|||
"The accumulator sequence can be accessed directly from inside a " { $link make } ":"
|
||||
{ $subsection building }
|
||||
{ $example
|
||||
"USING: make math.parser io ;"
|
||||
"USING: make math.parser ;"
|
||||
"[ \"Language #\" % CHAR: \\s , 5 # ] \"\" make print"
|
||||
"Language # 5"
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
USING: help.markup help.syntax kernel sequences words
|
||||
math strings vectors quotations generic effects classes
|
||||
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 ;
|
||||
IN: parser
|
||||
|
||||
|
@ -70,7 +70,8 @@ $nl
|
|||
{ $subsection "reading-ahead" }
|
||||
{ $subsection "parsing-word-nest" }
|
||||
{ $subsection "defining-words" }
|
||||
{ $subsection "parsing-tokens" } ;
|
||||
{ $subsection "parsing-tokens" }
|
||||
{ $subsection "word-search-parsing" } ;
|
||||
|
||||
ARTICLE: "parser-files" "Parsing source files"
|
||||
"The parser can run source files:"
|
||||
|
@ -84,7 +85,7 @@ $nl
|
|||
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."
|
||||
$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
|
||||
"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
|
||||
{ $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
|
||||
{ $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." }
|
||||
|
@ -247,4 +246,4 @@ HELP: staging-violation
|
|||
|
||||
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." }
|
||||
{ $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" } "." } ;
|
||||
|
|
|
@ -87,18 +87,6 @@ IN: parser.tests
|
|||
[ "OCT: 999" 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
|
||||
|
||||
"IN: parser.tests USING: math prettyprint ; SYNTAX: foo 2 2 + . ;" eval( -- )
|
||||
|
@ -596,7 +584,7 @@ EXCLUDE: qualified.tests.bar => x ;
|
|||
] 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
|
||||
] unit-test
|
||||
|
||||
|
@ -605,7 +593,7 @@ EXCLUDE: qualified.tests.bar => x ;
|
|||
] 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
|
||||
] unit-test
|
||||
|
||||
|
@ -614,7 +602,7 @@ EXCLUDE: qualified.tests.bar => x ;
|
|||
] 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
|
||||
] unit-test
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
USING: generic help.syntax help.markup kernel math parser words
|
||||
effects classes generic.standard classes.tuple generic.math
|
||||
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
|
||||
|
||||
ARTICLE: "parser-algorithm" "Parser algorithm"
|
||||
|
@ -179,7 +180,7 @@ $nl
|
|||
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" } "."
|
||||
{ $subsection "parser-algorithm" }
|
||||
{ $subsection "vocabulary-search" }
|
||||
{ $subsection "word-search" }
|
||||
{ $subsection "top-level-forms" }
|
||||
{ $subsection "syntax-comments" }
|
||||
{ $subsection "syntax-literals" }
|
||||
|
@ -427,18 +428,33 @@ HELP: FORGET:
|
|||
HELP: USE:
|
||||
{ $syntax "USE: vocabulary" }
|
||||
{ $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." } ;
|
||||
|
||||
HELP: USING:
|
||||
{ $syntax "USING: vocabularies... ;" }
|
||||
{ $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." } ;
|
||||
|
||||
HELP: QUALIFIED:
|
||||
{ $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
|
||||
"USING: prettyprint ;"
|
||||
"QUALIFIED: math"
|
||||
|
@ -447,7 +463,7 @@ HELP: QUALIFIED:
|
|||
|
||||
HELP: QUALIFIED-WITH:
|
||||
{ $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
|
||||
"USING: prettyprint ;"
|
||||
"QUALIFIED-WITH: math m"
|
||||
|
@ -457,19 +473,25 @@ HELP: QUALIFIED-WITH:
|
|||
|
||||
HELP: FROM:
|
||||
{ $syntax "FROM: vocab => words ... ;" }
|
||||
{ $description "Imports " { $snippet "words" } " from " { $snippet "vocab" } "." }
|
||||
{ $examples { $code
|
||||
"FROM: math.parser => bin> hex> ; ! imports only bin> and hex>" } } ;
|
||||
{ $description "Adds " { $snippet "words" } " from " { $snippet "vocab" } " to the search path." }
|
||||
{ $notes "If adding the words introduces ambiguity, the words will take precedence when resolving any ambiguous names." }
|
||||
{ $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:
|
||||
{ $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
|
||||
"EXCLUDE: math.parser => bin> hex> ; ! imports everything but bin> and hex>" } } ;
|
||||
"EXCLUDE: math.parser => bin> hex> ;" "! imports everything but bin> and hex>" } } ;
|
||||
|
||||
HELP: RENAME:
|
||||
{ $syntax "RENAME: word vocab => newname" }
|
||||
{ $description "Imports " { $snippet "word" } " from " { $snippet "vocab" } ", but renamed to " { $snippet "newname" } "." }
|
||||
{ $syntax "RENAME: word vocab => new-name" }
|
||||
{ $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
|
||||
"USING: prettyprint ;"
|
||||
"RENAME: + math => -"
|
||||
|
@ -740,7 +762,7 @@ HELP: MAIN:
|
|||
|
||||
HELP: <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
|
||||
"The following is an example of usage:"
|
||||
{ $code
|
||||
|
@ -770,7 +792,7 @@ HELP: <PRIVATE
|
|||
|
||||
HELP: 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
|
||||
|
||||
|
|
|
@ -49,6 +49,8 @@ IN: bootstrap.syntax
|
|||
|
||||
"USE:" [ scan use-vocab ] define-core-syntax
|
||||
|
||||
"UNUSE:" [ scan unuse-vocab ] define-core-syntax
|
||||
|
||||
"USING:" [ ";" parse-tokens [ use-vocab ] each ] define-core-syntax
|
||||
|
||||
"QUALIFIED:" [ scan dup add-qualified ] define-core-syntax
|
||||
|
|
|
@ -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
|
||||
|
||||
ARTICLE: "vocabulary-search-shadow" "Shadowing word names"
|
||||
"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"
|
||||
ARTICLE: "word-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."
|
||||
$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."
|
||||
|
@ -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."
|
||||
{ $subsection auto-use? } ;
|
||||
|
||||
ARTICLE: "vocabulary-search" "Vocabulary search path"
|
||||
"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."
|
||||
$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: }
|
||||
ARTICLE: "word-search-syntax" "Syntax to control word lookup"
|
||||
"Parsing words which make all words in a vocabulary available:"
|
||||
{ $subsection POSTPONE: USE: }
|
||||
{ $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-WITH: }
|
||||
"Parsing words which make a subset of all words in a vocabulary available:"
|
||||
{ $subsection POSTPONE: FROM: }
|
||||
{ $subsection POSTPONE: EXCLUDE: }
|
||||
{ $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
|
||||
"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 "vocabulary-search-errors" }
|
||||
{ $subsection "vocabulary-search-shadow" }
|
||||
{ $subsection POSTPONE: PRIVATE> } ;
|
||||
|
||||
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" } ;
|
||||
|
||||
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
|
||||
{ $var-description "A variable holding the current vocabulary search path as a sequence of assocs." } ;
|
||||
ABOUT: "word-search"
|
||||
|
||||
HELP: in
|
||||
{ $var-description "A variable holding the name of the current vocabulary for new definitions." } ;
|
||||
HELP: manifest
|
||||
{ $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
|
||||
{ $values { "str" "a vocabulary" } }
|
||||
{ $description "Returns the vocabulary stored in the " { $link in } " symbol. Throws an error if the current vocabulary is " { $link f } "." } ;
|
||||
HELP: <manifest>
|
||||
{ $values { "manifest" manifest } }
|
||||
{ $description "Creates a new manifest." } ;
|
||||
|
||||
HELP: (add-use)
|
||||
{ $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
|
||||
HELP: set-current-vocab
|
||||
{ $values { "name" string } }
|
||||
{ $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
|
||||
{ $values { "str" 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 } "." }
|
||||
{ $values { "name" string } { "word/f" { $maybe word } } }
|
||||
{ $description "Searches for a word by name in the current manifest. If no such word could be found, outputs " { $link f } "." }
|
||||
$parsing-note ;
|
||||
|
|
|
@ -32,8 +32,7 @@ M: manifest clone
|
|||
manifest get
|
||||
[ search-vocabs>> delete-all ]
|
||||
[ qualified-vocabs>> delete-all ]
|
||||
[ extra-words>> delete-all ]
|
||||
tri ;
|
||||
bi ;
|
||||
|
||||
: (use-vocab) ( vocab -- vocab seq )
|
||||
load-vocab manifest get search-vocabs>> ;
|
||||
|
@ -44,22 +43,25 @@ M: manifest clone
|
|||
: (from) ( vocab words -- vocab words words' assoc )
|
||||
2dup swap load-vocab words>> ;
|
||||
|
||||
: (use-words) ( assoc -- assoc seq )
|
||||
manifest get extra-words>> ;
|
||||
|
||||
: extract-words ( seq assoc -- assoc' )
|
||||
extract-keys dup [ [ drop ] [ no-word-error ] if ] assoc-each ;
|
||||
|
||||
: (lookup) ( name assoc -- word/f )
|
||||
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>
|
||||
|
||||
: set-current-vocab ( name -- )
|
||||
create-vocab manifest get
|
||||
[ (>>current-vocab) ]
|
||||
[ [ words>> ] dip extra-words>> push ]
|
||||
2bi ;
|
||||
create-vocab
|
||||
[ manifest get (>>current-vocab) ]
|
||||
[ words>> <extra-words> (add-qualified) ] bi ;
|
||||
|
||||
TUPLE: no-current-vocab ;
|
||||
|
||||
|
@ -124,9 +126,9 @@ TUPLE: rename word vocab words ;
|
|||
: add-renamed-word ( word vocab new-name -- )
|
||||
<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 ;
|
||||
|
||||
|
@ -148,17 +150,10 @@ ERROR: ambiguous-use-error words ;
|
|||
qualified-vocabs>>
|
||||
(vocab-search) 0 = [ drop f ] [ peek ] if ;
|
||||
|
||||
: word-search ( name manifest -- word/f )
|
||||
extra-words>> [ (lookup) ] with map-find-last drop ;
|
||||
|
||||
PRIVATE>
|
||||
|
||||
: search-manifest ( name manifest -- word/f )
|
||||
2dup word-search dup [ 2nip ] [
|
||||
drop 2dup qualified-search dup [ 2nip ] [
|
||||
drop vocab-search
|
||||
] if
|
||||
] if ;
|
||||
2dup qualified-search dup [ 2nip ] [ drop vocab-search ] if ;
|
||||
|
||||
: search ( name -- word/f )
|
||||
manifest get search-manifest ;
|
||||
|
|
|
@ -8,7 +8,7 @@ ARTICLE: "interned-words" "Looking up and creating words"
|
|||
$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."
|
||||
$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-in }
|
||||
{ $subsection lookup } ;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
USING: accessors arrays bank calendar kernel math math.functions
|
||||
namespaces make tools.test tools.walker ;
|
||||
FROM: bank => balance>> ;
|
||||
IN: bank.tests
|
||||
|
||||
SYMBOL: my-account
|
||||
|
|
|
@ -36,10 +36,8 @@ MEMO: (vocab-words) ( name -- seq )
|
|||
|
||||
: current-words ( -- seq )
|
||||
manifest get
|
||||
[ search-vocabs>> [ words>> ] map ]
|
||||
[ qualified-vocabs>> [ words>> ] map ]
|
||||
[ extra-words>> ]
|
||||
tri 3append assoc-combine keys ; inline
|
||||
[ search-vocabs>> ] [ qualified-vocabs>> ] bi [ words>> ] bi@
|
||||
assoc-union keys ; inline
|
||||
|
||||
: vocabs-words ( names -- seq )
|
||||
prune [ (vocab-words) ] map concat ; inline
|
||||
|
|
|
@ -54,7 +54,7 @@ $nl
|
|||
}
|
||||
"The standard precedence rules apply: Grouping with parentheses before " { $snippet "*" } ", " { $snippet "/" } "and " { $snippet "%" } " before " { $snippet "+" } " and " { $snippet "-" } "."
|
||||
{ $example
|
||||
"USING: infix prettyprint ;"
|
||||
"USE: infix"
|
||||
"[infix 5-40/10*2 infix] ."
|
||||
"-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."
|
||||
}
|
||||
{ $example
|
||||
"USING: infix locals math math.functions prettyprint ;"
|
||||
"USING: infix locals math.functions ;"
|
||||
":: binary_entropy ( p -- h )"
|
||||
" [infix -(p*log(p) + (1-p)*log(1-p)) / log(2) infix] ;"
|
||||
"[infix binary_entropy( sqrt(0.25) ) infix] ."
|
||||
|
@ -74,13 +74,13 @@ $nl
|
|||
$nl
|
||||
"You can access " { $vocab-link "sequences" } " inside infix expressions with the familiar " { $snippet "arr[index]" } " notation."
|
||||
{ $example
|
||||
"USING: arrays infix prettyprint ;"
|
||||
"USING: arrays infix ;"
|
||||
"[infix| myarr [ { 1 2 3 4 } ] | myarr[4/2]*3 infix] ."
|
||||
"9"
|
||||
}
|
||||
"Please note: in Factor " { $emphasis "fixnums are sequences too." } " If you are not careful with sequence accesses you may introduce subtle bugs:"
|
||||
{ $example
|
||||
"USING: arrays infix locals prettyprint ;"
|
||||
"USING: arrays infix locals ;"
|
||||
":: add-2nd-element ( x y -- res )"
|
||||
" [infix x[1] + y[1] infix] ;"
|
||||
"{ 1 2 3 } 5 add-2nd-element ."
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
! Copyright (C) 2008 Doug Coleman.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: tools.test math.floating-point math.constants kernel
|
||||
math.constants fry sequences kernel math ;
|
||||
USING: tools.test math.floating-point kernel
|
||||
math.constants fry sequences math ;
|
||||
IN: math.floating-point.tests
|
||||
|
||||
[ t ] [ pi >double< >double pi = ] unit-test
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
USING: tools.test math kernel sequences lists promises monads ;
|
||||
FROM: monads => do ;
|
||||
IN: monads.tests
|
||||
|
||||
[ 5 ] [ 1 identity-monad return [ 4 + ] fmap run-identity ] unit-test
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
! (c)2009 Joe Groff bsd license
|
||||
USING: accessors classes.tuple compiler.units kernel qw roles sequences
|
||||
tools.test ;
|
||||
FROM: roles => TUPLE: ;
|
||||
IN: roles.tests
|
||||
|
||||
ROLE: fork tines ;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
USING: accessors kernel tetris.game tetris.board tetris.piece tools.test
|
||||
sequences ;
|
||||
FROM: tetris.game => level>> ;
|
||||
|
||||
[ t ] [ <default-tetris> [ current-piece ] [ next-piece ] bi and t f ? ] unit-test
|
||||
[ t ] [ <default-tetris> { 1 1 } can-move? ] unit-test
|
||||
|
|
Loading…
Reference in New Issue