Documentation update

db4
Slava Pestov 2008-08-23 20:24:54 -05:00
parent 8ce6924702
commit 91059b4ad6
14 changed files with 192 additions and 76 deletions

View File

@ -52,9 +52,14 @@ ARTICLE: "standard-cli-args" "Command line switches for general usage"
{ { $snippet "-script" } { "Equivalent to " { $snippet "-quiet -run=none" } "." $nl "On Unix systems, Factor can be used for scripting - just create an executable text file whose first line is:" { $code "#! /usr/local/bin/factor -script" } "The space after " { $snippet "#!" } " is necessary because of Factor syntax." } }
} ;
ARTICLE: "cli" "Command line usage"
ARTICLE: "rc-files" "Running code on startup"
"Unless the " { $snippet "-no-user-init" } " command line switch is specified, The startup routine runs the " { $snippet ".factor-rc" } " file in the user's home directory, if it exists. This file can contain initialization and customization for your development environment."
$nl
"The " { $snippet ".factor-rc" } " and " { $snippet ".factor-boot-rc" } " files can be run explicitly:"
{ $subsection run-user-init }
{ $subsection run-bootstrap-init } ;
ARTICLE: "cli" "Command line usage"
"Zero or more command line arguments may be passed to the Factor runtime. Command line arguments starting with a dash (" { $snippet "-" } ") is interpreted as switches. All other arguments are taken to be file names to be run by " { $link run-file } "."
$nl
"Switches can take one of the following three forms:"
@ -68,9 +73,6 @@ $nl
{ $subsection "standard-cli-args" }
"The list of command line arguments can be obtained and inspected directly:"
{ $subsection cli-args }
"The " { $snippet ".factor-rc" } " and " { $snippet ".factor-boot-rc" } " files can be run explicitly:"
{ $subsection run-user-init }
{ $subsection run-bootstrap-init }
"There is a way to override the default vocabulary to run on startup:"
{ $subsection main-vocab-hook } ;

View File

@ -248,6 +248,7 @@ ARTICLE: "handbook-environment-reference" "Environment reference"
{ $subsection "prettyprint" }
{ $subsection "tools" }
{ $subsection "cli" }
{ $subsection "rc-files" }
{ $subsection "help" }
{ $subsection "inference" }
{ $subsection "compiler" }
@ -255,7 +256,8 @@ ARTICLE: "handbook-environment-reference" "Environment reference"
{ $subsection "images" }
{ $subsection "alien" }
{ $subsection "init" }
{ $subsection "layouts" } ;
{ $subsection "layouts" }
{ $see-also "program-org" } ;
ARTICLE: "handbook-library-reference" "Library reference"
"This index only includes articles from loaded vocabularies. To explore more vocabularies, see " { $link "vocab-index" } "."

View File

@ -258,14 +258,16 @@ M: string ($instance)
: $notes ( element -- )
"Notes" $heading print-element ;
: ($see) ( word -- )
: ($see) ( word quot -- )
[
snippet-style get [
code-style get [ see ] with-nesting
code-style get swap with-nesting
] with-style
] ($block) ;
] ($block) ; inline
: $see ( element -- ) first ($see) ;
: $see ( element -- ) first [ see ] ($see) ;
: $synopsis ( element -- ) first [ synopsis write ] ($see) ;
: $definition ( element -- )
"Definition" $heading $see ;

View File

@ -3,7 +3,7 @@ IN: macros
HELP: MACRO:
{ $syntax "MACRO: word ( inputs... -- ) definition... ;" }
{ $description "Defines a compile-time code transformation. If all inputs to the word are literal, then the macro body is invoked at compile-time to produce a quotation; this quotation is then spliced into the compiled code. If the inputs are not literal, or if the word is invoked from interpreted code, the macro body will execute every time and the result will be passed to " { $link call } "."
{ $description "Defines a compile-time code transformation. If all inputs to the word are literal and the word calling the macro has a static stack effect, then the macro body is invoked at compile-time to produce a quotation; this quotation is then spliced into the compiled code. If the inputs are not literal, or if the word is invoked from a word which does not have a static stack effect, the macro body will execute every time and the result will be passed to " { $link call } "."
$nl
"The stack effect declaration must be present because it tells the compiler how many literal inputs to expect."
}

View File

@ -4,34 +4,13 @@ IN: stack-checker.errors
HELP: literal-expected
{ $error-description "Thrown when inference encounters a " { $link call } " or " { $link if } " being applied to a value which is not known to be a literal. Such a form can have an arbitrary stack effect, and does not compile." }
{ $notes "This error will be thrown when compiling any combinator, such as " { $link each } ". However, words calling combinators can compile if the combinator is declared " { $link POSTPONE: inline } " and the quotation being passed in is a literal." } ;
HELP: too-many->r
{ $error-description "Thrown if inference notices a quotation pushing elements on the retain stack without popping them at the end." }
{ $notes "See " { $link "shuffle-words" } " for retain stack usage conventions." } ;
HELP: too-many-r>
{ $error-description "Thrown if inference notices a quotation popping elements from the return stack it did not place there." }
{ $notes "See " { $link "shuffle-words" } " for retain stack usage conventions." } ;
HELP: cannot-infer-effect
{ $values { "word" word } }
{ $description "Throws a " { $link cannot-infer-effect } " error." }
{ $error-description "Thrown when inference encounters a call to a word which is already known not to have a static stack effect, due to a prior inference attempt failing." } ;
HELP: effect-error
{ $values { "word" word } { "effect" "an instance of " { $link effect } } }
{ $description "Throws an " { $link effect-error } "." }
{ $error-description "Thrown when a word's inferred stack effect does not match its declared stack effect." } ;
HELP: missing-effect
{ $error-description "Thrown when inference encounters a word lacking a stack effect declaration. Stack effects of words must be declared, with the exception of words which only push literals on the stack." } ;
HELP: recursive-quotation-error
{ $error-description "Thrown when a quotation calls itself, directly or indirectly, within the same word. Stack effect inference becomes equivalent to the halting problem if quotation recursion has to be taken into account, hence it is not permitted." }
{ $notes "This error will be thrown when compiling any combinator, such as " { $link each } ". However, words calling combinators can compile if the combinator is declared " { $link POSTPONE: inline } " and the quotation being passed in is a literal." }
{ $examples
"Here is an example of quotation recursion:"
{ $code "[ [ dup call ] dup call ] infer." }
"In this example, words calling " { $snippet "literal-expected-example" } " will compile, even if " { $snippet "literal-expected-example" } " does not compile itself:"
{ $code
": literal-expected-example ( quot -- )"
" [ call ] [ call ] bi ; inline"
}
} ;
HELP: unbalanced-branches-error
@ -40,19 +19,109 @@ HELP: unbalanced-branches-error
{ $error-description "Thrown when inference encounters an " { $link if } " or " { $link dispatch } " where the branches do not all exit with the same stack height." }
{ $notes "Conditionals with variable stack effects are considered to be bad style and should be avoided since they do not compile."
$nl
"If this error comes up when inferring the stack effect of a recursive word, check the word's stack effect declaration; it might be wrong." } ;
"If this error comes up when inferring the stack effect of a recursive word, check the word's stack effect declaration; it might be wrong." }
{ $examples
{ $code
": unbalanced-branches-example ( a b c -- )"
" [ + ] [ dup ] if ;"
}
} ;
ARTICLE: "inference-errors" "Inference errors"
"Main wrapper for all inference errors:"
HELP: too-many->r
{ $error-description "Thrown if inference notices a quotation pushing elements on the retain stack without popping them at the end." }
{ $examples
{ $code
": too-many->r-example ( a b -- )"
" >r 3 + >r ;"
}
} ;
HELP: too-many-r>
{ $error-description "Thrown if inference notices a quotation popping elements from the return stack it did not place there." }
{ $examples
{ $code
": too-many-r>-example ( a b -- )"
" r> 3 + >r ;"
}
} ;
HELP: cannot-infer-effect
{ $values { "word" word } }
{ $description "Throws a " { $link cannot-infer-effect } " error." }
{ $error-description "Thrown when inference encounters a call to a word which is already known not to have a static stack effect, due to a prior inference attempt failing." } ;
HELP: missing-effect
{ $error-description "Thrown when inference encounters a word lacking a stack effect declaration. Stack effects of words must be declared, with the exception of words which only push literals on the stack." }
{ $examples
{ $code
": missing-effect-example"
" + * ;"
}
} ;
HELP: effect-error
{ $values { "word" word } { "effect" "an instance of " { $link effect } } }
{ $description "Throws an " { $link effect-error } "." }
{ $error-description "Thrown when a word's inferred stack effect does not match its declared stack effect." } ;
HELP: recursive-quotation-error
{ $error-description "Thrown when a quotation calls itself, directly or indirectly, within the same word. Stack effect inference becomes equivalent to the halting problem if quotation recursion has to be taken into account, hence it is not permitted." }
{ $examples
"Here is an example of quotation recursion:"
{ $code "[ [ dup call ] dup call ] infer." }
} ;
HELP: undeclared-recursion-error
{ $error-description "Thrown when an " { $link POSTPONE: inline } " word which is not declared " { $link POSTPONE: recursive } " calls itself, directly or indirectly. The " { $link POSTPONE: recursive } " declaration is mandatory for such words." } ;
HELP: diverging-recursion-error
{ $error-description "Thrown when stack effect inference determines that a recursive word might take an arbitrary number of values from the stack." }
{ $notes "Such words do not have a static stack effect and most likely indicate programmer error." }
{ $examples
{ $code
": diverging-recursion-example ( -- )"
" [ diverging-recursion-example f ] when ; inline recursive"
}
} ;
HELP: unbalanced-recursion-error
{ $error-description "Thrown when stack effect inference determines that an inline recursive word has an incorrect stack effect declaration." }
{ $examples
{ $code
": unbalanced-recursion-example ( quot: ( -- ? ) -- b )"
" dup call [ unbalanced-recursion-example ] [ drop ] if ;"
" inline recursive"
}
} ;
HELP: inconsistent-recursive-call-error
{ $error-description "Thrown when stack effect inference determines that an inline recursive word calls itself with a different set of quotation parameters than were input." }
{ $examples
{ $code
": inconsistent-recursive-call-example ( quot: ( -- ? ) -- b )"
" [ not ] compose inconsistent-recursive-call-example ; inline recursive"
}
} ;
ARTICLE: "inference-errors" "Inference warnings and errors"
"Main wrapper for all inference warnings and errors:"
{ $subsection inference-error }
"Specific inference errors:"
{ $subsection cannot-infer-effect }
"Inference warnings:"
{ $subsection literal-expected }
{ $subsection too-many->r }
{ $subsection too-many-r> }
{ $subsection cannot-infer-effect }
"Inference errors:"
{ $subsection recursive-quotation-error }
{ $subsection unbalanced-branches-error }
{ $subsection effect-error }
{ $subsection missing-effect } ;
{ $subsection missing-effect }
"Inference errors for inline recursive words:"
{ $subsection undeclared-recursion-error }
{ $subsection diverging-recursion-error }
{ $subsection unbalanced-recursion-error }
{ $subsection inconsistent-recursive-call-error }
"Retain stack usage errors:"
{ $subsection too-many->r }
{ $subsection too-many-r> }
"See " { $link "shuffle-words" } " for retain stack usage conventions. This error can only occur if your code calls " { $link >r } " and " { $link r> } " directly. The " { $link dip } " combinator is safer to use because there is no way to leave the retain stack in an unbalanced state." ;
ABOUT: "inference-errors"

View File

@ -45,15 +45,21 @@ $nl
"The call to " { $link if } " takes one value from the stack, a generalized boolean. The first branch " { $snippet "[ + ]" } " has stack effect " { $snippet "( x x -- x )" } " and the second has stack effect " { $snippet "( x -- )" } ". Since both branches decrease the height of the stack by one, we say that the stack effect of the two branches is " { $snippet "( x x -- x )" } ", and together with the boolean popped off the stack by " { $link if } ", this gives a total stack effect of " { $snippet "( x x x -- x )" } "." ;
ARTICLE: "inference-recursive" "Stack effects of recursive words"
"Recursive words must declare a stack effect. When a recursive call is encountered, the declared stack effect is substituted in. When inference is complete, the inferred stack effect is compared with the declared stack effect."
"When a recursive call is encountered, the declared stack effect is substituted in. When inference is complete, the inferred stack effect is compared with the declared stack effect."
$nl
"Attempting to infer the stack effect of a recursive word which outputs a variable number of objects on the stack will fail. For example, the following will throw an " { $link unbalanced-branches-error } ":"
{ $code ": foo ( seq -- ) dup empty? [ drop ] [ dup pop foo ] if" "[ foo ] infer." }
"If you declare an incorrect stack effect, inference will fail also. Badly defined recursive words cannot confuse the inferencer." ;
ARTICLE: "inference-limitations" "Inference limitations"
"Mutually recursive words are supported, but mutually recursive " { $emphasis "inline" } " words are not."
ARTICLE: "inference-recursive-combinators" "Recursive combinator inference"
"Most combinators are not explicitly recursive; instead, they are implemented in terms of existing combinators, for example " { $link while } ", " { $link map } ", and the " { $link "compositional-combinators" } "."
$nl
"Combinators which are recursive require additional care."
$nl
"If a recursive word takes quotation parameters from the stack and calls them, it must be declared " { $link POSTPONE: inline } " (as documented in " { $link "inference-combinators" } ") as well as " { $link POSTPONE: recursive } "."
$nl
"Furthermore, the input parameters which are quotations must be annotated in the stack effect. For example,"
{ $see loop }
"An inline recursive word cannot pass a quotation through the recursive call. For example, the following will not infer:"
{ $code ": foo ( a b c -- d e f ) [ f foo drop ] when 2dup call ; inline" "[ 1 [ 1+ ] foo ] infer." }
"However a small change can be made:"
@ -82,10 +88,10 @@ $nl
$nl
"The following articles describe the implementation of the stack effect inference algorithm:"
{ $subsection "inference-simple" }
{ $subsection "inference-combinators" }
{ $subsection "inference-branches" }
{ $subsection "inference-recursive" }
{ $subsection "inference-limitations" }
{ $subsection "inference-combinators" }
{ $subsection "inference-recursive-combinators" }
{ $subsection "inference-branches" }
{ $subsection "inference-errors" }
{ $subsection "compiler-transforms" }
{ $see-also "effects" } ;

View File

@ -1,4 +1,5 @@
USING: tools.test tools.annotations math parser eval ;
USING: tools.test tools.annotations math parser eval
io.streams.string kernel ;
IN: tools.annotations.tests
: foo ;
@ -24,3 +25,16 @@ M: integer some-generic 1+ ;
[ ] [ \ some-generic reset ] unit-test
[ 2 ] [ 3 some-generic ] unit-test
! slava's bug
GENERIC: another-generic ( a -- b )
M: object another-generic ;
\ another-generic watch
[ ] [ "IN: tools.annotations.tests GENERIC: another-generic ( a -- b )" eval ] unit-test
[ ] [ \ another-generic reset ] unit-test
[ "" ] [ [ 3 another-generic drop ] with-string-writer ] unit-test

View File

@ -4,9 +4,11 @@ IN: effects
ARTICLE: "effect-declaration" "Stack effect declaration"
"Stack effects of words must be declared, with the exception of words which only push literals on the stack."
$nl
"Stack effects are declared with the following syntax:"
{ $code ": sq ( x -- y ) dup * ;" }
"A stack effect declaration is written in parentheses and lists word inputs and outputs, separated by " { $snippet "--" } ". Stack effect declarations are read in using a parsing word:"
"A stack effect declaration is written in parentheses and lists word inputs and outputs, separated by " { $snippet "--" } ". Here is an example:"
{ $synopsis sq }
"Parameters which are quotations can be declared by suffixing the parameter name with " { $snippet ":" } " and then writing a nested stack effect declaration:"
{ $synopsis while }
"Stack effect declarations are read in using a parsing word:"
{ $subsection POSTPONE: ( }
"Stack elements in a stack effect are ordered so that the top of the stack is on the right side. Each value can be named by a data type or description. The following are some examples of value names:"
{ $table
@ -24,9 +26,7 @@ $nl
{ { $snippet "dim" } "a screen dimension specified as a two-element array holding width and height values" }
{ { $snippet "*" } "when this symbol appears by itself in the list of outputs, it means the word unconditionally throws an error" }
}
"The stack effect inferencer verifies stack effect comments to ensure the correct number of inputs and outputs is listed. Value names are ignored; only their number matters. An error is thrown if a word's declared stack effect does not match its inferred stack effect."
$nl
"Recursive words must declare a stack effect in order to compile. This includes all generic words, due to how delegation is implemented." ;
"The stack effect inferencer verifies stack effect comments to ensure the correct number of inputs and outputs is listed. Value names are ignored; only their number matters. An error is thrown if a word's declared stack effect does not match its inferred stack effect. See " { $link "inference" } "." ;
ARTICLE: "effects" "Stack effects"
"A " { $emphasis "stack effect declaration" } ", for example " { $snippet "( x y -- z )" } " denotes that an operation takes two inputs, with " { $snippet "y" } " at the top of the stack, and returns one output."

View File

@ -170,15 +170,12 @@ M: sequence update-methods ( class seq -- )
] with each ;
: define-generic ( word combination -- )
over "combination" word-prop over = [
2drop
] [
over "combination" word-prop over = [ drop ] [
2dup "combination" set-word-prop
over "methods" word-prop values forget-all
over H{ } clone "methods" set-word-prop
dupd define-default-method
make-generic
] if ;
] if make-generic ;
M: generic subwords
[

View File

@ -37,11 +37,9 @@ $nl
{ $subsection r> }
"The top of the data stack is ``hidden'' between " { $link >r } " and " { $link r> } ":"
{ $example "1 2 3 >r .s r>" "1\n2" }
"Words must not leave objects on the retain stack, nor expect values to be there on entry. The retain stack is for local storage within a word only, and occurrences of " { $link >r } " and " { $link r> } " must be balanced inside a single quotation. One exception is the following trick involving " { $link if } "; values may be pushed on the retain stack before the condition value is computed, as long as both branches of the " { $link if } " pop the values off the retain stack before returning:"
{ $code
": foo ( m ? n -- m+n/n )"
" >r [ r> + ] [ drop r> ] if ; ! This is OK"
} ;
"Usages of " { $link >r } " and " { $link r> } " must be balanced within a single quotation; quotations are not permitted to pop retain stack elements they did not push, or leave elements on the retain stack after returning."
$nl
"The " { $link "inference" } " tool checks retain stack usage. The " { $link "slip-keep-combinators" } " combinators abstract out common retain stack usage patterns." ;
ARTICLE: "cleave-shuffle-equivalence" "Expressing shuffle words with cleave combinators"
"Cleave combinators are defined in terms of shuffle words, and mappings from certain shuffle idioms to cleave combinators are discussed in the documentation for " { $link bi } ", " { $link 2bi } ", " { $link 3bi } ", " { $link tri } ", " { $link 2tri } " and " { $link 3tri } "."
@ -160,14 +158,14 @@ $nl
{ $subsection both? }
{ $subsection either? } ;
ARTICLE: "slip-keep-combinators" "The slip and keep combinators"
ARTICLE: "slip-keep-combinators" "The dip, slip and keep combinators"
"The dip combinators invoke the quotation at the top of the stack, hiding the values underneath:"
{ $subsection dip }
{ $subsection 2dip }
"The slip combinators invoke a quotation further down on the stack. They are most useful for implementing other combinators:"
{ $subsection slip }
{ $subsection 2slip }
{ $subsection 3slip }
"The dip combinators invoke the quotation at the top of the stack, hiding the values underneath:"
{ $subsection dip }
{ $subsection 2dip }
"The keep combinators invoke a quotation which takes a number of values off the stack, and then they restore those values:"
{ $subsection keep }
{ $subsection 2keep }

View File

@ -7,7 +7,10 @@ ARTICLE: "images" "Images"
{ $subsection save-image }
{ $subsection save-image-and-exit }
"To start Factor with a custom image, use the " { $snippet "-i=" { $emphasis "image" } } " command line switch; see " { $link "runtime-cli-args" } "."
{ $see-also "tools.memory" } ;
$nl
"New images can be created from scratch:"
{ $subsection "bootstrap.image" }
{ $see-also "tools.memory" "tools.deploy" } ;
ABOUT: "images"

View File

@ -192,6 +192,11 @@ HELP: inline
"The non-optimizing quotation compiler ignores inlining declarations."
} ;
HELP: recursive
{ $syntax ": foo ... ; recursive" }
{ $description "Declares the most recently defined word as a recursive word." }
{ $notes "This declaration is only required for " { $link POSTPONE: inline } " words which call themselves. See " { $link "inference-recursive-combinators" } "." } ;
HELP: foldable
{ $syntax ": foo ... ; foldable" }
{ $description

View File

@ -1,12 +1,29 @@
USING: vocabs help.markup help.syntax words strings io ;
IN: vocabs.loader
ARTICLE: "vocabs.roots" "Vocabulary roots"
"The vocabulary loader searches for it in one of the root directories:"
{ $subsection vocab-roots }
"The default set of roots includes the following directories in the Factor source directory:"
{ $list
{ { $snippet "core" } " - essential system vocabularies such as " { $vocab-link "parser" } " and " { $vocab-link "sequences" } ". The vocabularies in this root constitute the boot image; see " { $link "bootstrap.image" } "." }
{ { $snippet "basis" } " - useful libraries and tools, such as " { $vocab-link "compiler" } ", " { $vocab-link "ui" } ", " { $vocab-link "calendar" } ", and so on." }
{ { $snippet "extra" } " - additional contributed libraries." }
{ { $snippet "work" } " - a root for vocabularies which are not intended to be contributed back to Factor." }
}
"Your own vocabularies should go into " { $snippet "extra" } " or " { $snippet "work" } ", depending on whether or not you intend to contribute them back to the Factor project. If you wish to work on vocabularies outside of the Factor source directory, create a " { $snippet "~/.factor-rc" } " file like the following,"
{ $code
"USING: namespaces sequences vocabs.loader ;"
"\"/home/jane/sources/\" vocab-roots get push"
}
"See " { $link "rc-files" } " for details." ;
ARTICLE: "vocabs.loader" "Vocabulary loader"
"The vocabulary loader is defined in the " { $vocab-link "vocabs.loader" } " vocabulary."
$nl
"Vocabulary names map directly to source files. When a vocabulary which has not been loaded is accessed, the vocabulary loader searches for it in one of the root directories:"
{ $subsection vocab-roots }
"A vocabulary named " { $snippet "foo.bar" } " must be defined in a " { $snippet "bar" } " directory nested inside a " { $snippet "foo" } " directory at the vocabulary root. Any level of vocabulary nesting is permitted."
"Vocabularies are searched for in vocabulary roots."
{ $subsection "vocabs.roots" }
"Vocabulary names map directly to source files. A vocabulary named " { $snippet "foo.bar" } " must be defined in a " { $snippet "bar" } " directory nested inside a " { $snippet "foo" } " directory of a vocabulary root. Any level of vocabulary nesting is permitted."
$nl
"The vocabulary directory - " { $snippet "bar" } " in our example - can contain the following files; the first is required while the rest are optional:"
{ $list

View File

@ -80,6 +80,7 @@ $nl
{ $subsection POSTPONE: inline }
{ $subsection POSTPONE: foldable }
{ $subsection POSTPONE: flushable }
{ $subsection POSTPONE: recursive }
"Stack effect declarations are documented in " { $link "effect-declaration" } "." ;
ARTICLE: "word-definition" "Defining words"