factor/core/handbook/tools.facts

244 lines
12 KiB
Plaintext

USING: definitions errors help image tools io kernel
listener memory modules parser prettyprint sequences test
words shells interpreter completion inspector ;
ARTICLE: "tools" "Development tools"
"This section covers words which are used during development, and not usually invoked directly by user code."
$nl
"There are two useful development tools which are complex enough that separate sections are devoted to them; see " { $link "inference" } " and " { $link "compiler" } "."
{ $subsection "listener" }
{ $subsection "debugger" }
{ $subsection "editor" }
{ $subsection "definitions" }
{ $subsection "word-introspection" }
{ $subsection "inspector" }
{ $subsection "annotations" }
{ $subsection "sources" }
{ $subsection "images" }
{ $subsection "memory" }
{ $subsection "timing" }
"Meta-tools which can be used for implementing new tools:"
{ $subsection "completion" }
{ $subsection "meta-interpreter" } ;
ARTICLE: "listener" "The listener"
"The listener evaluates Factor expressions read from a stream. The listener is the primary interface to the Factor runtime. Typically, you write Factor code in a text editor, then load it using the listener and test it."
$nl
"The classical first program can be run in the listener:"
{ $example "\"Hello, world\" print" "Hello, world" }
"Multi-line phrases are supported:"
{ $example "{ 1 2 3 } [\n .\n] each" "1\n2\n3" }
"The listener knows when to expect more input by looking at the height of the stack. Parsing words such as " { $link POSTPONE: { } " leave elements on the parser stack, and corresponding words such as " { $link POSTPONE: } } " pop them."
$nl
"A very common operation is to inspect the contents of the data stack in the listener:"
{ $subsection .s }
"Note that calls to " { $link .s } " can also be included inside words as a debugging aid, however a more convenient way to achieve this is to use the annotation facility. See " { $link "annotations" } "."
$nl
"You can start a nested listener or exit a listener using the following words:"
{ $subsection tty }
{ $subsection bye }
"The following variables can be rebound inside a nested scope to customize the behavior of a listener; this can be done to create a development tool with a custom interaction loop:"
{ $subsection listener-hook }
"Finally, the multi-line expression reading word can be used independently of the rest of the listener:"
{ $subsection parse-interactive } ;
ARTICLE: "editor" "Editor integration"
"Factor development is best done with one of the supported editors; this allows you to quickly jump to definitions from the Factor environment."
$nl
"Depending on the editor you are using, you must load one of the following modules using " { $link require } ":"
{ $list
{ $module-link "libs/emacs" }
{ $module-link "libs/jedit" }
{ $module-link "libs/textmate" }
{ $module-link "libs/vim" }
}
"These modules store a quotation in a global variable when loaded:"
{ $subsection edit-hook }
{ $see-also edit "definitions" :edit "debugger" } ;
ARTICLE: "sources" "Source files"
"The simplest way to distribute a piece of Factor code is in the form of a source file. Source files can be loaded in the listener:"
{ $subsection run-file }
"Factor tracks which source files definitions were loaded from; see " { $link "definitions" } "."
$nl
"Details on the Factor source parser itself can be found in " { $link "parser" } "."
$nl
"Modules in the " { $snippet "apps/" } " and " { $snippet "libs/" } " directories of the Factor distribution should be loaded via the high-level module system instead of the above words (" { $link "modules" } ")." ;
ARTICLE: "debugger" "The debugger"
"If an expression entered in the listener throws an error, the error is printed to the output stream. A number of words facilitate interactive debugging of the error:"
{ $subsection :s }
{ $subsection :r }
{ $subsection :c }
{ $subsection :get }
"You can get a more detailed explanation as most types of errors are documented:"
{ $subsection :help }
"If the error was recoverable, a list of restarts is also printed, and a numbered restart can be invoked:"
{ $subsection :res }
"If the error was a syntax error thrown by " { $link run-file } " or " { $link require } " while loading a source file, you can jump to the location of the error in your editor:"
{ $subsection :edit }
"You can read more about error handling in " { $link "errors" } "." ;
ARTICLE: "inspector" "The inspector"
"The prettyprinter (see " { $link "prettyprint" } ") can turn any object into a source representation. Sometimes this source representation is hard to read for a human, so the inspector provides an alternative tabular view of an object:"
{ $subsection inspect }
"The inspector supports a number of commands which operate on the most recently inspected object:"
{ $subsection &push }
{ $subsection &back }
{ $subsection &at }
{ $subsection &put }
{ $subsection &add }
{ $subsection &rename }
{ $subsection &delete }
"A word for getting very brief descriptions of words and general objects:"
{ $subsection summary } ;
ARTICLE: "memory" "Object memory"
"You can print object heap status information:"
{ $subsection room. }
{ $subsection heap-stats. }
"Alternative forms of the above words return data on the stack instead of printing:"
{ $subsection data-room }
{ $subsection code-room }
{ $subsection heap-stats }
"There are a pair of combinators, analogous to " { $link each } " and " { $link subset } ", which operate on the entire collection of objects in the object heap:"
{ $subsection each-object }
{ $subsection instances }
"You can request the amount of heap memory used by an object:"
{ $subsection size }
"The garbage collector can be invoked manually:"
{ $subsection data-gc }
{ $subsection code-gc } ;
ARTICLE: "word-introspection" "Word introspection"
"Words support the definition protocol; see " { $link "definitions" } " for general tools that work with definitions. A few word-specific tools also exist:"
{ $subsection apropos }
{ $subsection vocabs }
{ $subsection words }
{ $subsection usage. } ;
ARTICLE: "definitions" "Definitions"
"A " { $emphasis "definition" } " is something read from a source file -- this includes words, methods, and help articles."
$nl
"Words that work with definition take " { $emphasis "definition specifiers" } " as input. A definition specifier is one of the following:"
{ $list
"a word"
"a two-element array, holding a class name and a generic word name, naming a method"
{ "a " { $link link } " instance holding a word or a help topic, naming a piece of documentation" }
}
"The following words all accept definition specifiers."
$nl
"Obtaining information about definitions:"
{ $subsection see }
{ $subsection where }
"Editing definitions:"
{ $subsection edit }
{ $subsection reload }
"Removing definitions:"
{ $subsection forget }
{ $link POSTPONE: FORGET: } ;
ARTICLE: "timing" "Timing code"
"You can time the execution of a quotation in the listener:"
{ $subsection time }
"A lower-level word puts timings on the stack, intead of printing:"
{ $subsection benchmark }
"You can also read the system clock and total garbage collection time directly:"
{ $subsection millis }
{ $subsection gc-time } ;
ARTICLE: "annotations" "Word annotations"
"The word annotation feature modifies word definitions to add debugging code. You can restore the old definition by calling " { $link reload } " on the word in question."
{ $subsection watch }
{ $subsection breakpoint }
{ $subsection breakpoint-if }
"All of the above words are implemented using a single combinator which applies a quotation to a word definition to yield a new definition:"
{ $subsection annotate } ;
ARTICLE: "images" "Working with images"
"Factor is an " { $emphasis "image-based" } " system, meaning it integrates a persistence mechanism where the object heap can be checkpointed to disk and loaded back in. Every time Factor runs, it starts by loading an image. The image contains all code and data needed to run Factor in a \"ready-to-go\" form."
$nl
"Image files are loaded by launching the Factor runtime with the image file as the first command line argument. Images are saved using one of the following two words; the latter takes an image path as a parameter:"
{ $subsection save }
{ $subsection save-image }
"A new image can also be built from sources; this is known as " { $emphasis "bootstrap" } ". Bootstrap is a two-step process. The first stage is the creation of a bootstrap image inside a running Factor instance:"
{ $subsection make-image }
"The second bootstrapping stage is initiated by running the resulting bootstrap image:"
{ $code "f -i=boot.image.pentium4" }
"This stage loads any additional platform-specific code, compiles all words, and dumps a final " { $snippet "factor.image" } "."
$nl
"The bootstrap image supports a number of command line arguments; see " { $link "bootstrap-cli-args" } "." ;
ARTICLE: "completion" "Fuzzy completion"
"The " { $link apropos } " word and " { $link "ui-completion" } " use the same fuzzy completion algorithm. It is sufficiently general-purpose that it can help with the implementation of custom development tools."
$nl
"The main entry point:"
{ $subsection completions }
"The words used to implement the algorithm can be called as well, for finer control over fuzzy matching:"
{ $subsection fuzzy }
{ $subsection runs }
{ $subsection score }
{ $subsection complete }
{ $subsection rank-completions } ;
ARTICLE: "meta-interp-state" "Interpreter state"
"The current interpreter state is stored in a number of variables:"
{ $subsection meta-interp }
{ $subsection callframe }
{ $subsection callframe-scan }
"A set of utility words for inspecting and modifying interpreter state is provided:"
{ $subsection meta-d }
{ $subsection push-d }
{ $subsection pop-d }
{ $subsection peek-d }
{ $subsection meta-r }
{ $subsection push-r }
{ $subsection pop-r }
{ $subsection peek-r }
{ $subsection meta-c }
{ $subsection push-c }
{ $subsection pop-c }
{ $subsection peek-c }
"Calling a quotation in the meta-circular interpreter:"
{ $subsection meta-call } ;
ARTICLE: "meta-interp-step" "Single-stepping words"
"Breakpoints can be inserted in user code:"
{ $subsection break }
"Breakpoints invoke a hook:"
{ $subsection break-hook }
"Single stepping with the meta-circular interpreter:"
{ $subsection step }
{ $subsection step-in }
{ $subsection step-out }
{ $subsection step-all }
{ $subsection abandon } ;
ARTICLE: "meta-interp-travel" "Backwards time travel"
"Backwards time travel is implemented by capturing the continuation after every step. Since this consumes additional memory, it must be explicitly enabled by storing an empty vector into a variable:"
{ $subsection meta-history }
"If this variable holds a vector, the interpreter state is automatically saved after every step. It can be saved at other points manually:"
{ $subsection save-interp }
"You can also restore any prior state:"
{ $subsection restore-interp }
"Or restore the most recently saved state:"
{ $subsection step-back } ;
ARTICLE: "meta-interp-impl" "Interpreter implementation"
"Custom single stepping behavior can be implemented by calling the common factor shared by " { $link step } " and " { $link step-in } ":"
{ $subsection next }
"The meta-circular interpreter executes most words much like the Factor interpreter; primitives are executed atomically and compound words are descended into. These semantics can be customized by setting the " { $snippet "\"meta-word\"" } " word property to a quotation. This quotation is run in the host interpreter and can make use of the words in " { $link "meta-interp-state" } "."
$nl
"Additionally, the " { $snippet "\"no-meta-word\"" } " word property can be set to " { $link t } " to instruct the meta-circular interpreter to always execute the word atomically, even if " { $link step-in } " is called." ;
ARTICLE: "meta-interpreter" "Meta-circular interpreter"
"The meta-circular interpreter is used to implement the walker tool in the UI. If you are simply interested in single stepping through a piece of code, use the " { $link "ui-walker" } "."
$nl
"On the other hand, if you want to implement a similar tool yourself, then you can use the words described in this section."
$nl
"Meta-circular interpreter words are found in the " { $vocab-link "interpreter" } " vocabulary."
{ $subsection "meta-interp-state" }
{ $subsection "meta-interp-step" }
{ $subsection "meta-interp-travel" }
{ $subsection "meta-interp-impl" } ;