"Sometimes an additional storage area is needed to hold objects. The " { $emphasis "retain stack" } " is an auxilliary stack for this purpose. Objects can be moved between the data and retain stacks using the following two words:"
{ $subsection >r }
{ $subsection r> }
"The top of the data stack is ``hidden'' between " { $link >r } " and " { $link r> } ":"
{ $example "1 2 3 >r .s r>" "2\n1" }
"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:"
"A quotation is a sequence of objects, some of which may be words. When evaluating a quotation, the interpreter executes words, and pushes other types of objects on the stack."
"In detail, the interpreter algorithm proceeds as follows:"
{ $list
{ "If the end of the current quotation has been reached, the parent quotation is popped from the call stack and execution resumes from the saved location" }
{ "Otherwise, the interpreter performs an action depending on the type of the object at the instruction pointer:"
{ $list
{ { $emphasis "Symbol word" } " - pushed on the datastack. See " { $link "symbols" } }
{ { $emphasis "Compound word" } " - the associated quotation is called. See " { $link "colon-definition" } }
{ { $emphasis "Compiled or primitive word" } " - the interpreter jumps to machine code. See " { $link "primitives" } }
{ { $emphasis "Undefined word" } " - an error is raised. See " { $link "deferred" } }
{ { $emphasis "Wrapper" } " - the wrapped object is pushed on the data stack. Wrappers are used to push word objects directly on the stack when they would otherwise execute. See the " { $link POSTPONE: \ } " parsing word." }
{ "All other types of objects are pushed on the data stack." }
}
}
}
"At each stage, the instruction pointer is advanced by one position."
$terpri
"The compiler generates machine code which perform the steps in a more efficient manner than the interpreter, however the observable semantics remain the same."
$terpri
"The following pair of words are central. They invoke the interpreter reflectively, allowing higher-order programming and meta-programming techniques that lie at the heart of Factor's expressive power."
"These words are used to implement " { $emphasis "combinators" } ", which are words that take code from the stack. Combinator definitions must be followed by the " { $link POSTPONE: inline } " declaration in order to compile; for example:"
{ $code
": keep ( x quot -- x | quot: x -- )"
" over >r call r> ; inline"
}
"Word inlining is documented in " { $link "declarations" } "."
"When a call is made to a quotation from the last word in the call frame, there is no purpose in pushing the empty call frame on the call stack. Therefore the last call in a quotation does not grow the call stack, and tail recursion executes in bounded space." ;
"There are some words that combine shuffle words with " { $link call } ". They are useful for implementing combinators."
{ $subsection slip }
{ $subsection 2slip }
{ $subsection keep }
{ $subsection 2keep }
{ $subsection 3keep }
{ $subsection 2apply } ;
ARTICLE: "conditionals" "Conditionals and boolean logic"
"In Factor, any object that is not " { $link f } " has a true boolean value, and " { $link f } " has a false boolean value."
$terpri
"The basic conditionals:"
{ $subsection if }
{ $subsection when }
{ $subsection unless }
"A form encapsulating a common stack shuffle pattern:"
{ $subsection if* }
{ $subsection when* }
{ $subsection unless* }
"Another form encapsulating a common stack shuffle pattern:"
{ $subsection ?if }
"Sometimes instead of executing one of two quotations, you just need to pick one of two values:"
{ $subsection ? }
"There are some logical operations on booleans:"
{ $subsection >boolean }
{ $subsection and }
{ $subsection or } ;
ARTICLE: "continuations" "Continuations"
"At any point in the execution of a program, the " { $emphasis "current continuation" } " represents the future of the computation. This object can be reified with the following two words:"
{ $subsection callcc0 }
{ $subsection callcc1 }
"Another two words resume continuations:"
{ $subsection continue }
{ $subsection continue-with }
"Continuations serve as the building block for a number of higher-level abstractions."
{ $subsection "errors" }
{ $subsection "threads" }
{ $subsection "continuations-internals" } ;
ARTICLE: "errors" "Handling errors"
"Support for handling exceptional situations such as bad user input, implementation bugs, and input/output errors is provided by a set of words built using continuations."
$terpri
"Two words raise an error in the innermost error handler for the current dynamic extent:"
{ $subsection throw }
{ $subsection rethrow }
"A set of words establish an error handler:"
{ $subsection cleanup }
{ $subsection recover }
{ $subsection catch }
"Caught errors can be logged in human-readable form:"