176 lines
8.5 KiB
Plaintext
176 lines
8.5 KiB
Plaintext
USING: errors help kernel namespaces threads words ;
|
|
|
|
ARTICLE: "dataflow" "Data and control flow"
|
|
{ $subsection "shuffle-words" }
|
|
{ $subsection "quotations" }
|
|
{ $subsection "combinators" }
|
|
{ $subsection "conditionals" }
|
|
{ $subsection "interpreter" }
|
|
{ $subsection "continuations" } ;
|
|
|
|
ARTICLE: "shuffle-words" "Shuffle words"
|
|
"Shuffle words rearrange items at the top of the data stack. They control the flow of data between words that perform actions."
|
|
$terpri
|
|
"Removing stack elements:"
|
|
{ $subsection drop }
|
|
{ $subsection 2drop }
|
|
{ $subsection 3drop }
|
|
{ $subsection nip }
|
|
{ $subsection 2nip }
|
|
"Duplicating stack elements:"
|
|
{ $subsection dup }
|
|
{ $subsection 2dup }
|
|
{ $subsection 3dup }
|
|
{ $subsection dupd }
|
|
{ $subsection over }
|
|
{ $subsection pick }
|
|
{ $subsection tuck }
|
|
"Permuting stack elements:"
|
|
{ $subsection swap }
|
|
{ $subsection rot }
|
|
{ $subsection -rot }
|
|
{ $subsection 2swap }
|
|
{ $subsection swapd }
|
|
"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:"
|
|
{ $code
|
|
": foo ( m ? n -- m+n/n )"
|
|
" >r [ r> + ] [ drop r> ] if ; ! This is OK"
|
|
} ;
|
|
|
|
ARTICLE: "quotations" "Quotations"
|
|
"Conceptually, a quotation is a snippet of code which can be passed around and called. Concretely, a quotation is a sequence of objects, some of which may be words. When evaluating a quotation, the interpreter looks at each element in turn, and executes words while pushing other types of objects on the stack. Details can be found in " { $link "interpreter" } "."
|
|
$terpri
|
|
"Quotation literal syntax is documented in " { $link "syntax-quots" } "."
|
|
$terpri
|
|
"Quotations implement the sequence protocol (" { $link "sequences" } "). Much of the power of Factor comes from the fact that not only can you have literal quotations in your program, but you can also construct new quotations at run time using general sequence words, or the following quotation-specific words:"
|
|
{ $subsection unit }
|
|
{ $subsection literalize }
|
|
{ $subsection curry }
|
|
{ $subsection alist>quot } ;
|
|
|
|
ARTICLE: "combinators" "Combinators"
|
|
"The following pair of words invoke the interpreter reflectively:"
|
|
{ $subsection call }
|
|
{ $subsection execute }
|
|
"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" } "."
|
|
$terpri
|
|
"There are some words that combine shuffle words with " { $link call } ". They are useful for implementing higher-level 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 }
|
|
"A form used when multiple conditional tests are to be performed:"
|
|
{ $subsection cond }
|
|
"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: "interpreter" "The interpreter"
|
|
"The interpreter runs in a loop which repeatedly performs the following steps:"
|
|
{ $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 data stack. 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
|
|
"If the instruction pointer is at the end of a quotation when a nested quotation is called, the quotation which just finished executing is not pushed on the call stack. Therefore the last call in a quotation does not grow the call stack, and tail recursion executes in bounded space."
|
|
$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." ;
|
|
|
|
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" "Error handling"
|
|
"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:"
|
|
{ $subsection error. }
|
|
{ $subsection try }
|
|
"Information relating to the most recently thrown error is stored in a pair of global variables:"
|
|
{ $subsection error }
|
|
{ $subsection error-continuation }
|
|
"Support for recoverable errors is built on top of the basic error handling facility. The following word signals a recoverable error:"
|
|
{ $subsection condition }
|
|
"Unhandled errors are reported in the listener and can be debugged using various tools. See " { $link "debugger" } "." ;
|
|
|
|
ARTICLE: "threads" "Multitasking"
|
|
"Continuations are used to implements co-operative multitasking, where the runtime switches between threads during I/O calls, and explicit yields."
|
|
{ $subsection in-thread }
|
|
{ $subsection yield }
|
|
{ $subsection sleep }
|
|
{ $subsection stop }
|
|
"Multitasking relies on a very simple round-robin scheduler:"
|
|
{ $subsection run-queue }
|
|
{ $subsection sleep-queue }
|
|
{ $subsection schedule-thread }
|
|
{ $subsection schedule-thread-with } ;
|
|
|
|
ARTICLE: "continuations-internals" "Continuation implementation details"
|
|
"A continuation is simply a tuple holding the contents of the five stacks:"
|
|
{ $subsection continuation }
|
|
"The five stacks can be read and written:"
|
|
{ $subsection datastack }
|
|
{ $subsection set-datastack }
|
|
{ $subsection retainstack }
|
|
{ $subsection set-retainstack }
|
|
{ $subsection callstack }
|
|
{ $subsection set-callstack }
|
|
{ $subsection namestack }
|
|
{ $subsection set-namestack }
|
|
{ $subsection catchstack }
|
|
{ $subsection set-catchstack } ;
|