Documentation and module system updates

darcs
slava 2006-06-20 00:14:33 +00:00
parent 50ec1d36db
commit 3786fe695f
12 changed files with 160 additions and 49 deletions

View File

@ -112,6 +112,6 @@ USING: namespaces words ;
<splay-tree> "foo" set <splay-tree> "foo" set
all-words [ dup word-name "foo" get set-splay ] each all-words [ dup word-name "foo" get set-splay ] each
all-words [ dup word-name "foo" get get-splay drop ] each all-words [ word-name "foo" get get-splay drop ] each
PROVIDE: splay-trees ; PROVIDE: splay-trees ;

View File

@ -179,8 +179,10 @@ ARTICLE: "cookbook-sources" "Source file cookbook"
"You can load source files from the Factor source code directory using " { $link run-resource } ":" "You can load source files from the Factor source code directory using " { $link run-resource } ":"
{ $code "\"/examples/lcd.factor\" run-resource" } { $code "\"/examples/lcd.factor\" run-resource" }
{ $references { $references
"You can learn more about parsing external content:" { }
"parse-stream" "sources"
"modules"
"parser"
} ; } ;
ARTICLE: "cookbook-io" "I/O cookbook" ARTICLE: "cookbook-io" "I/O cookbook"

View File

@ -8,26 +8,17 @@ $terpri
"As documented in " { $link "vocabulary-search" } ", the parser looks up words in the vocabulary search path. New word definitions are added to the current vocabulary. These two parameters are stored in a pair of variables:" "As documented in " { $link "vocabulary-search" } ", the parser looks up words in the vocabulary search path. New word definitions are added to the current vocabulary. These two parameters are stored in a pair of variables:"
{ $subsection use } { $subsection use }
{ $subsection in } { $subsection in }
"There are two simple ways to call the parser:" "There are two simple ways to call the parser which use the vocabulary search path currently in scope, which is usually the default listener search path:"
{ $subsection parse } { $subsection parse }
{ $subsection eval } { $subsection eval }
"More sophisticated facilities exist, too." "The parser can also take input from a stream (" { $link "streams" } "):"
{ $subsection "parse-stream" } { $subsection parse-stream }
"The parser can be extended with new parsing word definitions."
{ $subsection "parsing-words" } ;
ARTICLE: "parse-stream" "Parsing from streams"
"By convention, words for parsing input from streams use a certain default vocabulary search path:" "By convention, words for parsing input from streams use a certain default vocabulary search path:"
{ $subsection file-vocabs } { $subsection file-vocabs }
"The central word for parsing input from a stream:" "More details on working with source files can be found in " { $link "sources" } "."
{ $subsection parse-stream } $terpri
"Utilities for working with files:" "The parser can be extended with new parsing word definitions."
{ $subsection parse-file } { $subsection "parsing-words" } ;
{ $subsection run-file }
"Utilities for working with Factor libarary files:"
{ $subsection resource-path }
{ $subsection parse-resource }
{ $subsection run-resource } ;
ARTICLE: "parsing-words" "Parsing words" ARTICLE: "parsing-words" "Parsing words"
"Parsing words execute at parse time, and therefore can access and modify the state of the parser, as well as add objects to the parse tree. Parsing words are a difficult concept to grasp, so this section has several examples and explains the workings of some of the parsing words provided in the library." "Parsing words execute at parse time, and therefore can access and modify the state of the parser, as well as add objects to the parse tree. Parsing words are a difficult concept to grasp, so this section has several examples and explains the workings of some of the parsing words provided in the library."

View File

@ -1,17 +1,24 @@
USING: errors help image inspector kernel listener memory parser USING: errors help image inspector io kernel listener memory
prettyprint sequences test walker words ; modules parser prettyprint sequences test walker words ;
ARTICLE: "tools" "Development tools" ARTICLE: "tools" "Development tools"
"This section covers words which are used during development, and not usually invoked directly by user code." "This section covers words which are used during development, and not usually invoked directly by user code."
$terpri
"Interactive development:"
{ $subsection "listener" } { $subsection "listener" }
{ $subsection "debugger" } { $subsection "debugger" }
{ $subsection "inspector" }
{ $subsection "memory" }
{ $subsection "word-introspection" } { $subsection "word-introspection" }
{ $subsection "inspector" }
{ $subsection "walker" }
{ $subsection "annotations" } { $subsection "annotations" }
{ $subsection "timing" } "Working on a project:"
{ $subsection "sources" }
{ $subsection "modules" }
{ $subsection "images" }
{ $subsection "unit-test" } { $subsection "unit-test" }
{ $subsection "images" } ; "Advanced features:"
{ $subsection "memory" }
{ $subsection "timing" } ;
ARTICLE: "listener" "The listener" 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." "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."
@ -26,9 +33,6 @@ $terpri
{ $subsection .s } { $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" } "." "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" } "."
$terpri $terpri
"Source files can be loaded in:"
{ $subsection run-file }
{ $subsection reload }
"You can start a nested listener or exit a listener using the following words:" "You can start a nested listener or exit a listener using the following words:"
{ $subsection listener } { $subsection listener }
{ $subsection bye } { $subsection bye }
@ -39,6 +43,42 @@ $terpri
"Finally, the multi-line expression reading word can be used independently of the rest of the listener:" "Finally, the multi-line expression reading word can be used independently of the rest of the listener:"
{ $subsection read-multiline } ; { $subsection read-multiline } ;
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 }
"Another way to load a source file is to provide a path relative to the Factor installation directory:"
{ $subsection run-resource }
"Words remember which source file defines them; this can be used to update word definitions during development:"
{ $subsection reload }
"Details on the Factor source parser itself can be found in " { $link "parser" } "."
$terpri
"User-contributed libraries in the " { $snippet "contrib/" } " directory of the Factor distribution should be loaded via the high-level module system instead of the above words (" { $link "modules" } ")." ;
ARTICLE: "modules" "Modules and contributed libraries"
"The Factor distribution includes a selection of contributed libraries in the " { $snippet "contrib/" } " directory, which are managed by a simple module system."
$terpri
"To load " { $snippet "contrib/aim/" } " for instance, you simply issue the following command in the listener:"
{ $code "\"aim\" require" }
"The " { $link require } " word will load all dependencies and source files of the " { $snippet "aim" } " module."
{ $subsection require }
{ $subsection (require) }
"To define a new module named " { $snippet "frob" } ", create one of the following two files:"
{ $code "contrib/frob.factor" "contrib/frob/load.factor" }
"The module definition file should first list all required modules:"
{ $subsection POSTPONE: REQUIRES: }
"These modules will be loaded first. Next, the source files and unit tests, if any, have to be registered:"
{ $subsection POSTPONE: PROVIDE: }
"It is important that the module path name matches the module name passed to " { $link POSTPONE: PROVIDE: } ", which should be " { $snippet "frob" } " in the above example."
$terpri
"Here is a simple module definition taken from " { $snippet "contrib/concurrency/load.factor" } ":"
{ $code "REQUIRES: dlists ;"
"PROVIDE: concurrency"
"{ \"concurrency.factor\" }"
"{ \"concurrency-examples.factor\" \"concurrency-tests.factor\" } ;" }
"The following two words are useful during development of modules:"
{ $subsection load-module }
{ $subsection test-module } ;
ARTICLE: "debugger" "The debugger" 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:" "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 :s }

View File

@ -150,6 +150,8 @@ M: link summary "Link: " swap link-name append ;
: $definition ( content -- ) : $definition ( content -- )
"Definition" $heading $see ; "Definition" $heading $see ;
: $call ( content -- ) first call ;
: $curious ( content -- ) : $curious ( content -- )
"For the curious..." $heading print-element ; "For the curious..." $heading print-element ;

24
library/help/syntax.facts Normal file
View File

@ -0,0 +1,24 @@
USING: help ;
HELP: HELP: "word stack-effect content..."
{ $values { "word" "a word" } { "stack-effect" "a stack effect or syntax string" } { "content" "markup elements" } }
{ $description "Defines documentation for a word." }
{ $examples
{ $code
": foo 2 + ;"
"HELP: foo \"( m -- n )\""
"{ $values { \"m\" \"an integer\" } { \"n\" \"an integer\" } }"
"{ $description \"Increments a value by 2.\" } ;"
"\ foo help"
}
} ;
HELP: ARTICLE: "topic title content..."
{ $values { "topic" "a string" } { "title" "a string" } { "content" "markup elements" } }
{ $description "Defines a help article." }
{ $examples
{ $code
"ARTICLE: \"example\" \"An example article\""
"\"Hello world.\" ;"
}
} ;

View File

@ -45,7 +45,7 @@ HELP: <c-stream> "( in out -- stream )"
{ $notes "Usually C streams are only used during bootstrap, and non-blocking OS-specific I/O routines are used during normal operation." } ; { $notes "Usually C streams are only used during bootstrap, and non-blocking OS-specific I/O routines are used during normal operation." } ;
HELP: fopen "( path mode -- alien )" HELP: fopen "( path mode -- alien )"
{ $values { "path" "a pathname string" } { "mode" "an access mode specifier" } { "alien" "a C FILE* handle" } } { $values { "path" "a path name string" } { "mode" "an access mode specifier" } { "alien" "a C FILE* handle" } }
{ $description "Opens a file named by " { $snippet "path" } ". The " { $snippet "mode" } " parameter should be something like " { $snippet "\"r\"" } " or " { $snippet "\"rw\"" } "; consult the " { $snippet "fopen(3)" } " manual page for details." } { $description "Opens a file named by " { $snippet "path" } ". The " { $snippet "mode" } " parameter should be something like " { $snippet "\"r\"" } " or " { $snippet "\"rw\"" } "; consult the " { $snippet "fopen(3)" } " manual page for details." }
{ $errors "Throws an error if the file could not be opened." } { $errors "Throws an error if the file could not be opened." }
{ $notes "User code should call " { $link <file-reader> } " or " { $link <file-writer> } " to get a high level stream." } ; { $notes "User code should call " { $link <file-reader> } " or " { $link <file-writer> } " to get a high level stream." } ;

View File

@ -1,17 +1,17 @@
USING: help io ; USING: help io ;
HELP: cwd "( -- path )" HELP: cwd "( -- path )"
{ $values { "path" "a pathname string" } } { $values { "path" "a path name string" } }
{ $description "Outputs the current working directory of the Factor process." } { $description "Outputs the current working directory of the Factor process." }
{ $see-also cd } ; { $see-also cd } ;
HELP: cd "( path -- )" HELP: cd "( path -- )"
{ $values { "path" "a pathname string" } } { $values { "path" "a path name string" } }
{ $description "Changes the current working directory of the Factor process." } { $description "Changes the current working directory of the Factor process." }
{ $see-also cwd } ; { $see-also cwd } ;
HELP: stat "( path -- array/f )" HELP: stat "( path -- array/f )"
{ $values { "path" "a pathname string" } { "array/f" "a four-element array or " { $link f } } } { $values { "path" "a path name string" } { "array/f" "a four-element array or " { $link f } } }
{ $description { $description
"If the file does not exist, outputs " { $link f } ". Otherwise, outputs a four-element array:" "If the file does not exist, outputs " { $link f } ". Otherwise, outputs a four-element array:"
{ $list { $list

View File

@ -2,7 +2,7 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
IN: modules IN: modules
USING: compiler hashtables io kernel namespaces parser sequences USING: compiler hashtables io kernel namespaces parser sequences
words ; test words ;
TUPLE: module name files tests ; TUPLE: module name files tests ;
@ -27,26 +27,23 @@ H{ } clone modules set-global
: module modules get hash ; : module modules get hash ;
: require ( name -- ) : load-module ( name -- )
dup module [ "Loading module " write dup write "..." print
drop [ dup module-def run-resource ] assert-depth drop ;
] [
"Loading module " write dup write "..." print : (require) ( name -- )
module-def run-resource dup module [ drop ] [ load-module ] if ;
] if ;
: require ( name -- ) (require) compile-all ;
: run-resources ( seq -- ) : run-resources ( seq -- )
bootstrapping? get bootstrapping? get
[ parse-resource % ] [ run-resource ] ? each ; [ parse-resource % ] [ run-resource ] ? each ;
: load-module ( module -- ) module-files run-resources ;
: provide ( name files tests -- ) : provide ( name files tests -- )
<module> dup load-module <module> dup module-files run-resources
dup module-name modules get set-hash ; dup module-name modules get set-hash ;
: reload-module ( name -- ) module load-module ;
: test-module ( name -- ) module module-tests run-resources ; : test-module ( name -- ) module module-tests run-resources ;
: test-modules ( -- ) modules hash-keys [ test-module ] each ; : test-modules ( -- ) modules hash-keys [ test-module ] each ;

57
library/modules.facts Normal file
View File

@ -0,0 +1,57 @@
IN: modules
USING: help io ;
HELP: module-path "( name -- path )"
{ $values { "name" "a module name string" } { "path" "a path name string" } }
{ $description "Outputs the location of the module named " { $snippet "name" } "." } ;
HELP: module-paths "( name seq -- newseq )"
{ $values { "name" "a module name string" } { "seq" "a sequence of strings" } { "newseq" "a new sequence of path name strings" } }
{ $description "Prepend the location of the module named " { $snippet "name" } " to every file name in " { $snippet "seq" } "." } ;
HELP: module-def "( name -- path )"
{ $values { "name" "a module name string" } { "path" "a path name string" } }
{ $description "Outputs the location of the module definition file. This word looks for the module definition in two locations:"
{ $list
{ $snippet "contrib/" { $emphasis "name" } ".factor" }
{ $snippet "contrib/" { $emphasis "name" } "/load.factor" }
}
}
{ $notes "This file is loaded by " { $link require } ", and should contain the necessary " { $link POSTPONE: REQUIRES: } " and " { $link POSTPONE: PROVIDE: } " declarations for the module." } ;
HELP: modules f
{ $description "Variable. Hashtable mapping loaded module names to " { $link module } " instances." }
{ $see-also require reload-module } ;
HELP: load-module "( name -- )"
{ $values { "name" "a module name string" } }
{ $description "Runs the module definition file given by " { $link module-def } ", which loads the module's dependencies and source files." }
{ $notes "Unless you want to explicitly reload the sources of a module (for example, after making changes), you should use " { $link (require) } " or " { $link require } " instead." } ;
HELP: (require) "( name -- )"
{ $values { "name" "a module name string" } }
{ $description "Ensures that a module has been loaded, along with all its dependencies."
$terpri
"If this module is already listed in the " { $link modules } " hashtable, this word does nothing. Otherwise, it calls " { $link load-module } "." }
{ $notes "Module definitions should use the " { $link POSTPONE: REQUIRES: } " parsing word instead. In the listener, the " { $link require } " word might be more useful since it recompiles new words after loading the module." } ;
HELP: require "( name -- )"
{ $values { "name" "a module name string" } }
{ $description "Ensures that a module has been loaded, along with all its dependencies, and recompiles all new words. This word is only for interactive use in the listener; to avoid recompiling words multiple times, any user code which needs to load modules should call " { $link (require) } " instead." } ;
HELP: run-resources "( seq -- )"
{ $values { "seq" "a sequence of strings" } }
{ $description "Load a collection of source files identified by resource paths (see " { $link resource-path } ")."
$terpri
"If bootstrapping, this word appends the top-level forms to the currently constructing quotation instead." } ;
HELP: provide "( name files tests -- )"
{ $values { "name" "a string" } { "files" "a sequence of strings" } { "tests" "a sequence of strings" } }
{ $description "Registers a module definition and loads the source files. Usually instead of calling this word, module definitions use the parsing word " { $link POSTPONE: PROVIDE: } " instead." } ;
HELP: test-module "( name -- )"
{ $values { "name" "a module name string" } }
{ $description "Runs the unit test files associated to the module by a previous call to " { $link provide } " or " { $link POSTPONE: PROVIDE: } "." } ;
HELP: test-modules "( -- )"
{ $description "Runs unit test files for all loaded modules." } ;

View File

@ -77,8 +77,6 @@ DEFER: !PRIMITIVE: parsing
: !PROVIDE: : !PROVIDE:
scan [ { { } { } } append first2 provide ] f ; parsing scan [ { { } { } } append first2 provide ] f ; parsing
: !REQUIRE: scan require compile-all ; parsing
: !REQUIRES: : !REQUIRES:
string-mode on string-mode on
[ string-mode off [ require ] each ] f ; parsing [ string-mode off [ (require) ] each ] f ; parsing

View File

@ -93,7 +93,7 @@ global [
"scratchpad" "syntax" "arrays" "compiler" "scratchpad" "syntax" "arrays" "compiler"
"errors" "generic" "hashtables" "help" "inference" "errors" "generic" "hashtables" "help" "inference"
"inspector" "io" "jedit" "kernel" "listener" "math" "inspector" "io" "jedit" "kernel" "listener" "math"
"memory" "namespaces" "parser" "prettyprint" "memory" "modules" "namespaces" "parser" "prettyprint"
"sequences" "shells" "strings" "styles" "test" "sequences" "shells" "strings" "styles" "test"
"threads" "vectors" "walker" "words" "threads" "vectors" "walker" "words"
} set-use } set-use