more help system work

cvs
Slava Pestov 2005-12-30 08:57:38 +00:00
parent 7cbf796ad4
commit 7e65dffaee
16 changed files with 477 additions and 215 deletions

View File

@ -192,11 +192,18 @@ vectors words ;
"/library/help/stylesheet.factor"
"/library/help/help.factor"
"/library/help/markup.factor"
"/library/help/word-help.factor"
"/library/help/commands.factor"
"/library/help/syntax.factor"
"/library/help/tutorial.factor"
"/library/collections/growable.facts"
"/library/collections/arrays.facts"
"/library/collections/hashtables.facts"
"/library/collections/namespaces.facts"
"/library/collections/queues.facts"
"/library/syntax/parse-syntax.factor"
"/library/bootstrap/image.factor"

View File

@ -1,19 +1,34 @@
IN: arrays
USING: help lists prettyprint strings vectors ;
USING: help kernel-internals lists prettyprint strings vectors ;
GLOSSARY: "array"
"An instance of the" { $link array } "class, implementing a fixed-length mutable sequence of objects" ;
"an instance of the" { $link array } "class, implementing a fixed-length mutable sequence of objects" ;
ARTICLE: "arrays" "Arrays"
"An array is a fixed-size mutable sequence whose elements are stored in a contiguous range of memory. The literal syntax is covered in " { $link "array-literals" } ". Sometimes you need a growable array -- this is called a vector, and vectors are documented in " { $link "vectors" } "."
$terpri
"Array words are in the " { $snippet "arrays" } " vocabulary. Unsafe implementation words are in the " { $snippet "kernel-internals" } " vocabulary."
$terpri
"Arrays form a class of objects."
{ $subsection array }
{ $subsection array? }
"There are several ways to construct arrays."
{ $subsection >array }
{ $subsection <array> }
{ $subsection zero-array }
{ $subsection 1array }
{ $subsection 2array }
{ $subsection 3array }
"Arrays can be accessed without bounds checks in a pointer unsafe way."
{ $subsection array-nth }
{ $subsection set-array-nth } ;
HELP: <array> "( n elt -- array )"
{ $values { "n" "a positive integer specifying array length" } { "elt" "an initial element" } }
{ $description "Create a new array with the given length and all elements initially set to " { $parameter "elt" } "." }
{ $description "Create a new array with the given length and all elements initially set to " { $snippet "elt" } "." }
{ $examples { 3 f <array> . } }
{ $see-also <string> <sbuf> <vector> } ;
HELP: array? "( object -- ? )"
{ $predicate "array" }
{ $see-also string? sbuf? vector? } ;
HELP: >array "( seq -- array )"
{ $values { "seq" "a sequence" } { "array" "an array" } }
{ $description "Outputs a freshly-allocated array with the same elements as a given sequence." }

View File

@ -20,6 +20,7 @@ $terpri
HELP: set-fill "( n seq -- )"
{ $values { "n" "a new fill pointer" } { "seq" "a growable sequence" } }
{ $contract "Sets the fill pointer (number of occupied elements in the underlying storage) of a growable sequence." }
{ $side-effects "Modifies " { $snippet "seq" } "." }
{ $safety "This word is in the sequences-internals vocabulary because it is not safe. Changing the fill pointer to a negative value, or a value higher than the underlying sequence length can lead to memory corruption. Client code should use " { $link set-length } " instead." } ;
HELP: underlying "( seq -- underlying )"

View File

@ -1,3 +1,5 @@
! Copyright (C) 2004, 2005 Slava Pestov.
! See http://factor.sf.net/license.txt for BSD license.
IN: hashtables-internals
USING: arrays hashtables kernel math sequences
sequences-internals ;
@ -67,13 +69,6 @@ TUPLE: tombstone ;
2dup new-key@ swap [ underlying 2dup nth-unsafe ] keep
( value key n underlying old hash )
swap change-size set-nth-pair ;
: grow-hash
[ dup underlying swap hash-size 1+ ] keep
[ reset-hash ] keep swap [ swap pick (set-hash) ] each-pair
drop ;
: ?grow-hash
dup hash-count 3 * over underlying length >
[ dup grow-hash ] when drop ;
: hash>seq
underlying dup length 2 /i
@ -83,7 +78,6 @@ TUPLE: tombstone ;
IN: hashtables
: <hashtable> (hashtable) [ reset-hash ] keep ;
: associate 2 <hashtable> [ set-hash ] keep ;
: clear-hash [ underlying length ] keep reset-hash ;
: hash-size dup hash-count swap hash-deleted - ;
: hash-empty? hash-size 0 = ;
@ -105,7 +99,16 @@ IN: hashtables
] [
3drop
] if-key ;
: grow-hash
[ dup underlying swap hash-size 1+ ] keep
[ reset-hash ] keep swap [ swap pick (set-hash) ] each-pair
drop ;
: ?grow-hash
dup hash-count 3 * over underlying length >
[ dup grow-hash ] when drop ;
: set-hash [ (set-hash) ] keep ?grow-hash ;
: associate 2 <hashtable> [ set-hash ] keep ;
: ?set-hash [ [ set-hash ] keep ] [ associate ] if ;
: hash-keys 0 swap hash>seq ; : hash-values 1 swap hash>seq ;
: hash>alist dup hash-keys swap hash-values 2array flip ;
@ -139,13 +142,10 @@ IN: hashtables
inline
M: hashtable clone clone-growable ;
: subhash? ( h1 h2 -- ? )
#! Test if h2 contains all the key/value pairs of h1.
swap [
>r swap hash* [ r> = ] [ r> 2drop f ] if
] hash-all-with? ; flushable
: subhash?
swap
[ >r swap hash* [ r> = ] [ r> 2drop f ] if ]
hash-all-with? ; flushable
M: hashtable = ( obj hash -- ? )
{
{ [ 2dup eq? ] [ 2drop t ] }
@ -154,57 +154,18 @@ M: hashtable = ( obj hash -- ? )
{ [ t ] [ 2dup subhash? >r swap subhash? r> and ] }
} cond ;
: ?hash ( key hash/f -- value/f )
dup [ hash ] [ 2drop f ] if ; flushable
: ?hash* ( key hash/f -- value/f )
dup [ hash* ] [ 2drop f f ] if ; flushable
: ?set-hash ( value key hash/f -- hash )
[ 2 <hashtable> ] unless* [ set-hash ] keep ;
: hash-stack ( key seq -- value )
#! Searches for a key in a sequence of hashtables,
#! where the most recently pushed hashtable is searched
#! first.
[ dupd hash-member? ] find-last nip ?hash ; flushable
: hash-intersect ( hash1 hash2 -- hash1/\hash2 )
#! Remove all keys from hash2 not in hash1.
[ drop swap hash ] hash-subset-with ;
: hash-diff ( hash1 hash2 -- hash2-hash1 )
#! Remove all keys from hash2 in hash1.
[ drop swap hash not ] hash-subset-with ;
: hash-update ( hash1 hash2 -- )
#! Add all key/value pairs from hash2 to hash1.
[ swap rot set-hash ] hash-each-with ;
: hash-concat ( seq -- hash )
#! Combine a sequence of hashtables into one hashtable.
H{ } clone swap [ dupd hash-update ] each ;
: hash-union ( hash1 hash2 -- hash1\/hash2 )
#! Make a new hashtable with all key/value pairs from
#! hash1 and hash2. Values in hash2 take precedence.
>r clone dup r> hash-update ;
: remove-all ( hash seq -- seq )
#! Remove all elements from the sequence that are keys
#! in the hashtable.
[ swap hash-member? not ] subset-with ; flushable
: cache ( key hash quot -- value | quot: key -- value )
pick pick hash [
>r 3drop r>
] [
pick rot >r >r call dup r> r> set-hash
] if* ; inline
: map>hash ( seq quot -- hash | quot: key -- value )
#! Construct a hashtable with keys from the sequence, and
#! values obtained by applying the quotation to each key.
: hash-stack [ dupd hash-member? ] find-last nip ?hash ; flushable
: hash-intersect [ drop swap hash ] hash-subset-with ; flushable
: hash-diff [ drop swap hash not ] hash-subset-with ; flushable
: hash-update [ swap rot set-hash ] hash-each-with ;
: hash-concat H{ } clone [ dupd hash-update ] reduce ; flushable
: hash-union >r clone dup r> hash-update ; flushable
: remove-all [ swap hash-member? not ] subset-with ; flushable
: cache
pick pick hash
[ >r 3drop r> ]
[ pick rot >r >r call dup r> r> set-hash ] if* ; inline
: map>hash
swap [ length <hashtable> ] keep
[ -rot [ >r over >r call r> r> set-hash ] 2keep ] each nip ;
inline

View File

@ -1,15 +1,81 @@
IN: hashtables
USING: hashtables-internals help inspector prettyprint ;
USING: hashtables-internals help inspector kernel prettyprint ;
GLOSSARY: "hashtable"
"An instance of the " { $link hashtable } " class, implementing a mutable mapping from keys to values with expected constant lookup time" ;
GLOSSARY: "hashcode"
"an integer chosen so that equal objects have equal hashcodes, and unequal objects' hashcodes are distributed as evently as possible" ;
ARTICLE: "hashtables" "Hashtables"
"A hashtable provides efficient (expected constant time) lookup and storage of key/value pairs. Keys are compared for equality, and a hashing function is used to reduce the number of comparisons made."
$terpri
"Hashtable words are in the " { $snippet "hashtables" } " vocabulary. Unsafe implementation words are in the " { $snippet "hashtables-internals" } " vocabulary."
$terpri
"Hashtables form a class of objects."
{ $subsection hashcode }
{ $subsection hashtable? }
{ $subsection <hashtable> }
"There are some primitive operations on hashes, and many utilities."
{ $subsection "hashtables-lookup" }
{ $subsection "hashtables-mutation" }
{ $subsection "hashtables-combinators" }
{ $subsection "hashtables-utilities" }
{ $subsection "hashtables-internals" } ;
ARTICLE: "hashtables-lookup" "Looking up keys in hashtables"
{ $subsection hash }
{ $subsection hash* }
{ $subsection ?hash }
{ $subsection ?hash* }
{ $subsection hash-member? } ;
ARTICLE: "hashtables-mutation" "Storing keys in hashtables"
{ $subsection set-hash }
{ $subsection ?set-hash }
{ $subsection remove-hash }
{ $subsection clear-hash } ;
ARTICLE: "hashtables-combinators" "Hashtable combinators"
"We have the standard functional programming idioms."
{ $subsection hash-each }
{ $subsection hash-all? }
{ $subsection hash-subset }
"There are curried forms of the above."
{ $subsection hash-each-with }
{ $subsection hash-all-with? }
{ $subsection hash-subset-with }
"Two oddball combinators."
{ $subsection cache }
{ $subsection map>hash } ;
ARTICLE: "hashtables-utilities" "Hashtable utilities"
"Set-theoretic operations exploit the expected constant lookup time of a hashtable."
{ $subsection hash-intersect }
{ $subsection hash-diff }
{ $subsection hash-union }
{ $subsection hash-concat }
{ $subsection hash-update }
{ $subsection remove-all }
"A combinator used to implement notions of nested scope. This includes various fundamental abstractions like variables, vocabulary search and cascading styles."
{ $subsection hash-stack } ;
HELP: hashcode "( object -- n )"
{ $values { "object" "an object" } { "n" "an integer" } }
{ $contract "Outputs the hashcode of the object. The fundamental invariant that must never be violated is that if two objects are equal under " { $link = } ", they must have the same hashcode." }
{ $notes "If mutable objects are used as hashtable keys, they must not be mutated in such a way that their hashcode changes. Doing so will violate bucket sorting invariants and result in undefined behavior." } ;
ARTICLE: "hashtables-internals" "Hashtable implementation details"
"This hashtable implementation uses only one auxilliary array in addition to the hashtable tuple itself. The array stores keys in even slots and values in odd slots. Values are looked up with a hashing strategy that uses linear probing to resolve collisions."
{ $terpri }
"There are two special objects: the " { $link ((tombstone)) } " marker and the " { $link ((empty)) } " marker. Neither of these markers can be used as hashtable keys."
{ $terpri }
"The " { $link hash-count } " slot is the number of entries including deleted entries, and " { $link hash-deleted } " is the number of deleted entries." ;
"The " { $link hash-count } " slot is the number of entries including deleted entries, and " { $link hash-deleted } " is the number of deleted entries."
{ $subsection <hash-array> }
{ $subsection nth-pair }
{ $subsection set-nth-pair }
{ $subsection each-pair }
{ $subsection all-pairs? } ;
HELP: hash@ "( key array -- i )"
{ $values { "key" "a key" } { "array" "the underlying array of a hashtable" } { "i" "the index to begin hashtable search" } }
@ -100,7 +166,7 @@ HELP: hash>seq "( i hash -- seq )"
HELP: <hashtable> "( n -- hash )"
{ $values { "n" "a positive integer specifying hashtable capacity" } { "hash" "a new hashtable" } }
{ $description "Create a new hashtable capable of storing " { $parameter "n" } " key/value pairs before growing." }
{ $description "Create a new hashtable capable of storing " { $snippet "n" } " key/value pairs before growing." }
{ $see-also clear-hash hash-size hash-empty? } ;
HELP: associate "( value key -- hash )"
@ -122,7 +188,7 @@ HELP: hash-empty? "( hash -- ? )"
HELP: hash* "( key hash -- value ? )"
{ $values { "key" "an object to look up in the hashtable" } { "hash" "a hashtable" } { "value" "the value associated to the key, or " { $link f } " if the key is not present in the hashtable" } { "?" "a boolean indicating if the key was present" } }
{ $description "Looks up the value associated with a key. Keys are tested for equality. The boolean flag can decide between the case of a missing value, and a value of " { $link f } "." }
{ $description "Looks up the value associated with a key. The boolean flag can decide between the case of a missing value, and a value of " { $link f } "." }
{ $see-also hash-member? hash ?hash ?hash* } ;
HELP: hash-member? "( key hashtable -- ? )"
@ -137,7 +203,7 @@ HELP: ?hash* "( key hashtable/f -- ? )"
HELP: hash "( key hash -- value )"
{ $values { "key" "an object to look up in the hashtable" } { "hash" "a hashtable" } { "value" "the value associated to the key, or " { $link f } " if the key is not present in the hashtable" } }
{ $description "Looks up the value associated with a key. Keys are tested for equality. No distinction is made between a missing value and a value set to " { $link f } "." }
{ $description "Looks up the value associated with a key. No distinction is made between a missing value and a value set to " { $link f } "." }
{ $see-also hash-member? hash* ?hash ?hash* } ;
HELP: ?hash "( key hash/f -- ? )"
@ -155,6 +221,11 @@ HELP: set-hash "( key hash -- )"
{ $description "Stores an entry into the hashtable." }
{ $see-also hash remove-hash } ;
HELP: ?set-hash "( value key hash/f -- hash )"
{ $values { "value" "a value" } { "key" "a key" } { "hash/f" "a hashtable or " { $link f } } }
{ $description "If the mapping is " { $link f } ", constructs a new hashtable storing the given key/value pair. Otherwise, stores the key/value pair into the hashtable." }
{ $see-also hash remove-hash } ;
HELP: hash-keys "( hash -- keys )"
{ $values { "hash" "a hashtable" } { "keys" "an array of keys" } }
{ $description "Outputs an array of all keys in the hashtable." }
@ -189,3 +260,47 @@ HELP: hash-subset "( hash quot -- subhash )"
{ $values { "hash" "a hashtable" } { "quot" "a quotation with stack effect " { $snippet "( key value -- ? )" } } { "subhash" "a new hashtable" } }
{ $description "Constructs a hashtable consisting of all key/value pairs for which the predicate quotation yields true." }
{ $see-also hash-each hash-each-with hash-all? hash-all-with? hash-subset-with } ;
HELP: subhash? "( hash1 hash2 -- ? )"
{ $values { "hash1" "a hashtable" } { "hash2" "a hashtable" } { "?" "a new hashtable" } }
{ $description "Tests if " { $snippet "hash2" } " contains all key/value pairs of " { $snippet "hash1" } "." } ;
HELP: hash-stack "( key seq -- value )"
{ $values { "key" "a key" } { "seq" "a sequence of hashtables" } { "value" "a value or " { $link f } } }
{ $description "Looks up the key in every hashtable in the sequence, search from back to front. If the key could not be found, outputs " { $link f } ". This word is used to implement abstractions such as nested scopes; if the sequence is a stack represented by a vector, then the most recently pushed hashtable -- the innermost scope -- will be searched first." } ;
HELP: hash-intersect "( hash1 hash2 -- intersection )"
{ $values { "hash1" "a hashtable" } { "hash2" "a hashtable" } { "intersection" "a new hashtable" } }
{ $description "Constructs a hashstable consisting of all key/value pairs from " { $snippet "hash2" } " such that the key is also present in " { $snippet "hash1" } "." }
{ $notes "The values of the keys in " { $snippet "hash1" } " are disregarded, so this word is usually used for set-theoretic calculations where the hashtable in question either has dummy sentinels as values, or the values equal the keys." } ;
HELP: hash-diff "( hash1 hash2 -- difference )"
{ $values { "hash1" "a hashtable" } { "hash2" "a hashtable" } { "difference" "a new hashtable" } }
{ $description "Constructs a hashstable consisting of all key/value pairs from " { $snippet "hash2" } " such that the key is not present in " { $snippet "hash1" } "" }
{ $notes "The values of the keys in " { $snippet "hash1" } " are disregarded, so this word is usually used for set-theoretic calculations where the hashtable in question either has dummy sentinels as values, or the values equal the keys." } ;
HELP: hash-update "( hash1 hash2 -- )"
{ $values { "hash1" "a hashtable" } { "hash2" "a hashtable" } }
{ $description "Adds all key/value pairs from " { $snippet "hash2" } " to " { $snippet "hash1" } "." } ;
HELP: hash-concat "( seq -- hash )"
{ $values { "seq" "a sequence of hashtables" } { "hash" "a new hashtable" } }
{ $description "Constructs a hashtable by merging every element of the sequence, with key/value pairs in subsequent hashtables taking precedence." } ;
HELP: hash-union "( hash1 hash2 -- union )"
{ $values { "hash1" "a hashtable" } { "hash2" "a hashtable" } { "union" "a new hashtable" } }
{ $description "Constructs a hashstable consisting of all key/value pairs from " { $snippet "hash1" } " and " { $snippet "hash2" } ", with entries from " { $snippet "hash2" } " taking precedence." }
{ $notes "The values of the keys in " { $snippet "hash1" } " are disregarded, so this word is usually used for set-theoretic calculations where the hashtable in question either has dummy sentinels as values, or the values equal the keys." } ;
HELP: remove-all "( hash seq -- subseq )"
{ $values { "hash" "a hashtable" } { "seq" "a sequence" } { "subseq" "a new sequence" } }
{ $description "Constructs a sequence consisting of all elements from the sequence that appear as keys in the hashtable." }
{ $notes "The values of the keys in the hashtable are disregarded, so this word is usually used for set-theoretic calculations where the hashtable in question either has dummy sentinels as values, or the values equal the keys." } ;
HELP: cache "( key hash quot -- value )"
{ $values { "key" "a key" } { "hash" "a hashtable" } { "quot" "a quotation with stack effect " { $snippet "( key -- value )" } } { "value" "a previously-retained or freshly-computed value" } }
{ $description "If the key is present in the hashtable, outputs the associated value, otherwise calls the quotation to produce a value and stores the key/value pair into the hashtable." } ;
HELP: map>hash "( seq quot -- hash )"
{ $values { "seq" "a sequence" } { "quot" "a quotation with stack effect " { $snippet "( key -- value )" } } { "hash" "a hashtable" } { "value" "a previously-retained or freshly-computed value" } }
{ $description "Applies the quotation to each element of the sequence to produce a value corresponding to each key, and constructs a new hashtable from these key/value pairs." } ;

View File

@ -4,85 +4,36 @@ IN: namespaces
USING: arrays hashtables kernel kernel-internals lists math
sequences strings vectors words ;
! Variables in Factor:
!
! SYMBOL: x
!
! 5 x set
! x get 2 + .
! 7
! 7 x set
! x get 2 + .
! 9
!
! get ( name -- value ) and set ( value name -- ) search in
! the namespaces on the namespace stack, in top-down order.
!
! At the bottom of the namespace stack, is the global
! namespace; it is always present.
!
! bind ( namespace quot -- ) executes a quotation with a
! namespace pushed on the namespace stack.
: namestack* ( -- ns ) 3 getenv ; inline
: namestack ( -- ns ) namestack* clone ; inline
: set-namestack ( ns -- ) clone 3 setenv ; inline
: namespace ( -- namespace ) namestack* peek ; inline
: >n ( namespace -- n:namespace ) namestack* push ; inline
: n> ( n:namespace -- namespace ) namestack* pop ; inline
: global ( -- g ) 4 getenv ; inline
: get ( variable -- value ) namestack* hash-stack ; flushable
: set ( value variable -- ) namespace set-hash ;
: on ( var -- ) t swap set ; inline
: off ( var -- ) f swap set ; inline
: set-global ( value var -- ) global set-hash ; inline
: nest ( variable -- hash )
#! If the variable is set in the current namespace, return
#! its value, otherwise set its value to a new namespace.
dup namespace hash [ ] [ >r H{ } clone dup r> set ] ?if ;
: change ( var quot -- quot: old -- new )
#! Execute the quotation with the variable value on the
#! stack. The set the variable to the return value of the
#! quotation.
>r dup get r> rot slip set ; inline
: inc ( var -- ) [ 1+ ] change ; inline
: dec ( var -- ) [ 1- ] change ; inline
: bind ( namespace quot -- )
#! Execute a quotation with a namespace on the namestack.
swap >n call n> drop ; inline
: make-hash ( quot -- hash ) H{ } clone >n call n> ; inline
: with-scope ( quot -- ) make-hash drop ; inline
: namestack* 3 getenv ; inline
: namestack namestack* clone ; inline
: set-namestack clone 3 setenv ; inline
: namespace namestack* peek ; inline
: >n namestack* push ; inline
: n> namestack* pop ; inline
: global 4 getenv ; inline
: get namestack* hash-stack ; flushable
: set namespace set-hash ;
: on t swap set ; inline
: off f swap set ; inline
: set-global global set-hash ; inline
: nest dup namespace hash [ ] [ >r H{ } clone dup r> set ] ?if ;
: change >r dup get r> rot slip set ; inline
: inc [ 1+ ] change ; inline
: dec [ 1- ] change ; inline
: bind swap >n call n> drop ; inline
: make-hash H{ } clone >n call n> ; inline
: with-scope make-hash drop ; inline
! Building sequences
SYMBOL: building
: make ( quot proto -- )
#! Call , and % from "quot" to append to a sequence
#! that has the same type as "proto".
: make
[
dup thaw building set >r call building get r> like
] with-scope ; inline
: , ( obj -- )
#! Add to the sequence being built with make-seq.
building get push ;
: ?, ( obj ? -- ) [ , ] [ drop ] if ;
: % ( seq -- )
#! Append to the sequence being built with make-seq.
building get swap nappend ;
: # ( n -- )
#! Only useful with "" make.
number>string % ;
: , building get push ;
: ?, [ , ] [ drop ] if ;
: % building get swap nappend ;
: # number>string % ;
! Building hashtables, and computing a transitive closure.
SYMBOL: hash-buffer

View File

@ -0,0 +1,160 @@
IN: namespaces
USING: help ;
GLOSSARY: "namestack" "a stack holding namespaces. Entering a dynamic scope pushes the name stack, leaving a scope pops it" ;
GLOSSARY: "namespace" "a hashtable pushed on the name stack and used as a set of variable bindings" ;
GLOSSARY: "dynamic scope" "a variable binding policy where bindings established in a scope are visible to all code executed while the scope is active" ;
ARTICLE: "namespaces" "Variables and namespaces"
"A variable is an entry in a hashtable of bindings, with the hashtable being implicit rather than passed on the stack. These hashtables are termed " { $emphasis "namespaces" } ". Nesting of scopes is implemented with a search order on namespaces, defined by a " { $emphasis "namestack" } ". Since namespaces are just hashtables, any object can be used as a variable, however by convention, variables are keyed by symbols (see " { $link "symbols" } ")."
$terpri
"The " { $snippet "get" } " and " { $snippet "set" } " words read and write variable values. The " { $snippet "get" } " word searches up the chain of nested namespaces, while " { $snippet "set" } " always sets variable values in the current namespace only. Namespaces are dynamically scoped; when a quotation is called from a nested scope, any words called by the quotation also execute in that scope."
{ $subsection get }
{ $subsection set }
{ $subsection "namespaces-change" }
{ $subsection "namespaces-combinators" }
{ $subsection "namespaces-utilities" }
{ $subsection "namespaces-internals" } ;
ARTICLE: "namespaces-combinators" "Namespace combinators"
{ $subsection make-hash }
{ $subsection with-scope }
{ $subsection bind } ;
ARTICLE: "namespaces-change" "Ways to change variable values"
{ $subsection on }
{ $subsection off }
{ $subsection inc }
{ $subsection dec }
{ $subsection change } ;
ARTICLE: "namespaces-utilities" "Namespace utilities"
{ $subsection namespace }
{ $subsection nest }
{ $subsection global }
{ $subsection set-global } ;
ARTICLE: "namespaces-internals" "Namespace implementation details"
"The namestack holds namespaces."
{ $subsection namestack* }
{ $subsection namestack }
{ $subsection set-namestack }
"A pair of words push and pop namespaces on the namestack."
{ $subsection >n }
{ $subsection n> } ;
HELP: get "( variable -- value )"
{ $values { "variable" "a variable, by convention a symbol" } { "value" "the value, or " { $link f } } }
{ $description "Searches the namestack for a namespace containing the variable, and outputs the associated value. If no such namespace is found, outputs " { $link f } "." } ;
HELP: set "( value variable -- )"
{ $values { "value" "the new value" } { "variable" "a variable, by convention a symbol" } }
{ $description "Assigns a value to the variable in the namespace at the top of the namestack." }
{ $side-effects "variable" } ;
HELP: off "( variable -- )"
{ $values { "variable" "a variable, by convention a symbol" } }
{ $description "Assigns a value of " { $link f } " to the variable." }
{ $side-effects "variable" } ;
HELP: on "( variable -- ) "
{ $values { "variable" "a variable, by convention a symbol" } }
{ $description "Assigns a value of " { $link t } " to the variable." }
{ $side-effects "variable" } ;
HELP: change "( variable quot -- )"
{ $values { "variable" "a variable, by convention a symbol" } { "quot" "a quotation with stack effect " { $snippet "( old -- new )" } } }
{ $description "Applies the quotation to the old value of the variable, and assigns the resulting value to the variable." }
{ $side-effects "variable" } ;
HELP: inc "( variable -- ) "
{ $values { "variable" "a variable, by convention a symbol" } }
{ $description "Increments the value of the variable by 1." }
{ $errors "An error is thrown if the variable does not hold a number." }
{ $side-effects "variable" } ;
HELP: dec "( variable -- ) "
{ $values { "variable" "a variable, by convention a symbol" } }
{ $description "Decrements the value of the variable by 1." }
{ $errors "An error is thrown if the variable does not hold a number." }
{ $side-effects "variable" } ;
HELP: with-scope "( quot -- )"
{ $values { "quot" "a quotation" } }
{ $description "Calls the quotation in a new namespace. Any variables set by the quotation are discarded when it returns." } ;
HELP: make-hash "( quot -- hash )"
{ $values { "quot" "a quotation" } { "hash" "a new hashtable" } }
{ $description "Calls the quotation in a new namespace, and outputs this namespace when the quotation returns. Useful for quickly building hashtables." } ;
HELP: bind "( ns quot -- )"
{ $values { "ns" "a hashtable" } { "quot" "a quotation" } }
{ $description "Calls the quotation in the dynamic scope of " { $snippet "ns" } ". When variables are looked up by the quotation, " { $snippet "ns" } " is checked first, and setting variables in the quotation stores them in " { $snippet "ns" } "." } ;
HELP: namespace "( -- ns )"
{ $values { "ns" "a hashtable" } }
{ $description "Outputs the current namespace. Calls to " { $link set } " modify this namespace." } ;
HELP: global "( -- ns )"
{ $values { "ns" "a hashtable" } }
{ $description "Outputs the global namespace. The global namespace is always checked last when looking up variable values." } ;
HELP: set-global "( value variable -- )"
{ $values { "value" "the new value" } { "variable" "a variable, by convention a symbol" } }
{ $description "Assigns a value to the variable in the global namespace." }
{ $side-effects "variable" } ;
HELP: nest "( variable -- namespace )"
{ $values { "variable" "a variable, by convention a symbol" } { "namespace" "a hashtable" } }
{ $description "If the variable is not set in the current namespace, sets it to a new hashtable, and outputs this hashtable. Otherwise, outputs the existing value (which should probably be a hashtable)." }
{ $side-effects "variable" } ;
HELP: namestack* "( -- namestack )"
{ $values { "namestack" "a vector" } }
{ $description "Outputs the current namestack." } ;
HELP: namestack "( -- namestack )"
{ $values { "namestack" "a vector" } }
{ $description "Outputs a copy of the current namestack." } ;
HELP: set-namestack "( namestack -- )"
{ $values { "namestack" "a vector" } }
{ $description "Replaces the namestack with a copy of the given vector." } ;
HELP: >n "( ns -- )"
{ $values { "ns" "a hashtable" } }
{ $description "Pushes a namespace on the namestack." } ;
HELP: n> "( -- ns )"
{ $values { "ns" "a hashtable" } }
{ $description "Pops a namespace from the namestack." } ;
ARTICLE: "sequences-make" "Constructing sequences using an accumulator"
"The library supports an idiom where sequences can be constructed without passing the partial sequence being built on the stack. This reduces stack noise, and thus simplifies code and makes it easier to understand."
{ $subsection make }
{ $subsection , }
{ $subsection ?, }
{ $subsection % }
{ $subsection # } ;
HELP: make "( quot exemplar -- seq )"
{ $values { "quot" "a quotation" } { "exemplar" "a sequence" } }
{ $description "Calls the quotation in a new " { $emphasis "dynamic scope" } ". The quotation and any words it calls can execute the " { $link , } " and " { $link % } " words to accumulate elements. When the quotation returns, all accumulated elements are collected into a sequence with the same type as " { $snippet "exemplar" } "." ;
HELP: , "( elt -- )"
{ $values { "elt" "an object" } }
{ $description "Adds an element to the end of the sequence being constructed by " { $link make } "." } ;
HELP: ?, "( elt ? -- )"
{ $values { "elt" "an object" } { ">" "a boolean indicating of the element should be added or not" } }
{ $description "Conditionally adds an element to the end of the sequence being constructed by " { $link make } "." } ;
HELP: % "( seq -- )"
{ $values { "seq" "a sequence" } }
{ $description "Appends a sequence to the end of the sequence being constructed by " { $link make } "." } ;
HELP: # "( n -- )"
{ $values { "n" "a real number" } }
{ $description "Appends the string representation of a real number to the end of the sequence being constructed by " { $link make } "." } ;

View File

@ -2,23 +2,19 @@ IN: queues
USING: errors kernel lists math sequences vectors ;
TUPLE: queue in out ;
C: queue ( -- queue ) ;
: queue-empty? ( queue -- ? )
dup queue-in swap queue-out or not ;
: enque ( obj queue -- )
[ queue-in cons ] keep set-queue-in ;
: deque ( queue -- obj )
C: queue ;
: queue-empty? dup queue-in swap queue-out or not ;
: enque [ queue-in cons ] keep set-queue-in ;
: (deque)
dup queue-in [
reverse uncons pick set-queue-out
f rot set-queue-in
] [
"Empty queue" throw
] if* ;
: deque
dup queue-out [
uncons rot set-queue-out
] [
dup queue-in [
reverse uncons pick set-queue-out
f rot set-queue-in
] [
"Empty queue" throw
] if*
(deque)
] if* ;

View File

@ -0,0 +1,25 @@
IN: queues
USING: help ;
ARTICLE: "queues" "Queues"
"Last-in-first-out queues can be found in the " { $snippet "queues" } " vocabulary."
{ $subsection <queue> }
{ $subsection queue-empty? }
{ $subsection deque }
{ $subsection enque } ;
HELP: <queue> "( -- queue )"
{ $values { "queue" "a new queue" } }
{ $description "Makes a new queue with no elements." } ;
HELP: queue-empty? "( queue -- ? )"
{ $values { "queue" "a queue" } { "?" "a boolean" } }
{ $description "Tests if a queue contains no elements." } ;
HELP: deque "( queue -- elt )"
{ $values { "queue" "a queue" } { "elt" "an object" } }
{ $description "Removes an element from the front of the queue." } ;
HELP: enque "( elt queue -- )"
{ $values { "elt" "an object" } { "queue" "a queue" } }
{ $description "Adds an element to the back of the queue." } ;

View File

@ -4,17 +4,9 @@ IN: strings
USING: kernel math strings sequences-internals sequences ;
M: string resize resize-string ;
M: sbuf set-length ( n sbuf -- ) grow-length ;
M: sbuf nth-unsafe ( n sbuf -- ch ) underlying nth-unsafe ;
M: sbuf nth ( n sbuf -- ch ) bounds-check nth-unsafe ;
M: sbuf set-nth-unsafe ( ch n sbuf -- )
underlying set-nth-unsafe ;
M: sbuf set-nth ( ch n sbuf -- )
growable-check 2dup ensure set-nth-unsafe ;
M: sbuf set-length grow-length ;
M: sbuf nth-unsafe underlying nth-unsafe ;
M: sbuf nth bounds-check nth-unsafe ;
M: sbuf set-nth-unsafe underlying set-nth-unsafe ;
M: sbuf set-nth growable-check 2dup ensure set-nth-unsafe ;
M: sbuf clone clone-growable ;

View File

@ -0,0 +1,20 @@
IN: strings
USING: help ;
GLOSSARY: "string buffer" "an instance of the " { $link "sbuf" } " class, representing a mutable and growable sequence of characters" ;
GLOSSARY: "sbuf" "see string buffer" ;
ARTICLE: "sbufs" "String buffers"
"A string buffer is a mutable and growable sequence of characters. String buffers can be used to construct new strings by accumilating substrings and characters, however usually they are only used indirectly, since the sequence construction words (see " { $link "sequences-make" } " are more convenient to use in most cases."
$terpri
"String buffer words are found in the " { $snippet "strings" } " vocabulary."
$terpri
"String buffers form a class of objects."
{ $subsection sbuf? }
{ $subsection >sbuf }
{ $subsection <sbuf> } ;
HELP: ">sbuf" "( seq -- sbuf )"
{ $values { "seq" "a sequence of non-negative integers" } { "sbuf" "a string buffer" } }
{ $description "Turns a character sequence into a string buffer. Given a string buffer, this makes a fresh copy." } ;

View File

@ -2,7 +2,7 @@
! See http://factor.sf.net/license.txt for BSD license.
IN: strings
USING: generic kernel kernel-internals lists math namespaces
sequences strings ;
sequences strings vectors ;
: padding ( string count char -- string )
>r swap length - 0 max r> <string> ; flushable
@ -15,8 +15,7 @@ sequences strings ;
: ch>string ( ch -- str ) 1 swap <string> ; flushable
: >sbuf ( seq -- sbuf )
dup length <sbuf> [ swap nappend ] keep ; inline
: >sbuf dup length <sbuf> [ swap nappend ] keep ; inline
: >string ( seq -- array )
[ length 0 <string> 0 over ] keep copy-into ; inline
@ -28,3 +27,5 @@ M: string like ( seq sbuf -- string )
M: sbuf like ( seq sbuf -- sbuf )
drop dup sbuf? [ >sbuf ] unless ;
: a/an ( string -- ) first ch>lower "aeiou" member? "an " "a " ? ;

View File

@ -100,7 +100,7 @@ M: tuple = ( obj tuple -- ? )
2dup eq? [
2drop t
] [
over tuple? [ array= ] [ 2drop f ] if
over tuple? [ tuple= ] [ 2drop f ] if
] if ;
: is? ( obj pred -- ? | pred: obj -- ? )

View File

@ -21,22 +21,6 @@ M: string article-title article article-title ;
M: string article-content article article-content ;
! Word help
M: word article-title word-name ;
DEFER: $synopsis
DEFER: $definition
M: word article-content
[
dup "help" word-prop [
\ $synopsis pick 2array , %
] [
"Undocumented." ,
] if*
\ $definition swap 2array ,
] { } make ;
! Special case: f help
M: f article-title drop \ f word-name ;

View File

@ -3,7 +3,7 @@
IN: help
USING: arrays gadgets gadgets-panes gadgets-presentations
hashtables inspector io kernel lists namespaces prettyprint
sequences strings styles words ;
sequences strings styles vectors words ;
: uncons* dup first swap 1 swap tail ;
@ -104,20 +104,6 @@ M: simple-element print-element
: $see ( content -- )
code-style [ [ first see ] with-nesting* ] with-style ;
: $definition ( content -- )
"Definition" $subheading $see ;
: $predicate ( content -- )
{ { "object" "an object" } } $values
"Tests if the top of the stack is a " swap first "." append3
1array $description ;
: $list ( content -- )
terpri* [ "- " format* print-element terpri* ] each ;
: $safety ( content -- )
"Memory safety" $subheading print-element ;
! Some links
TUPLE: link name ;
@ -142,3 +128,28 @@ DEFER: help
: $link ( article -- ) first <link> ($link) simple-object ;
: $glossary ( element -- ) first <term> ($link) simple-object ;
: $definition ( content -- )
"Definition" $subheading $see ;
: $predicate ( content -- )
{ { "object" "an object" } } $values
"Tests if the top of the stack is " $description
dup first word-name a/an print-element $link
"." print-element ;
: $list ( content -- )
terpri* [ "- " format* print-element terpri* ] each ;
: $safety ( content -- )
"Memory safety" $subheading print-element ;
: $errors ( content -- )
"Errors" $subheading print-element ;
: $side-effects ( content -- )
"Side effects" $subheading "Modifies " print-element
[ $snippet ] [ "," format* bl ] interleave ;
: $notes ( content -- )
"Notes" $subheading print-element ;

View File

@ -0,0 +1,23 @@
IN: help
USING: arrays kernel namespaces words ;
! Word help
M: word article-title word-name ;
: word-help ( word -- )
dup "help" word-prop [
% drop
] [
dup "predicating" word-prop [
\ $predicate swap 2array ,
] [
"No documentation found for " , word-name , "." ,
] ?if
] if* ;
M: word article-content
[
\ $synopsis over 2array ,
dup word-help
\ $definition swap 2array ,
] { } make ;