100 lines
6.2 KiB
Plaintext
100 lines
6.2 KiB
Plaintext
USING: definitions errors help image tools io kernel
|
|
listener memory modules parser prettyprint sequences test
|
|
words shells ;
|
|
|
|
ARTICLE: "module-organization" "Module organization"
|
|
"Modules are loaded from the Factor directory, and are conventionally placed in one of four subdirectories therein:"
|
|
{ $list
|
|
{ { $snippet "core/" } " - core library and language" }
|
|
{ { $snippet "apps/" } " - complete applications written in Factor" }
|
|
{ { $snippet "libs/" } " - additional libraries written in Factor" }
|
|
{ { $snippet "demos/" } " - small examples demonstrating language features" }
|
|
}
|
|
"A module named " { $snippet "libs/frob" } " must be defined in a file whose name takes one of the following two forms:"
|
|
{ $code "libs/frob.factor" "libs/frob/load.factor" }
|
|
"The former should only be used for very small modules; if your module needs unit tests, documentation or more than one source file (as most do), you need to create a new directory with a " { $snippet "load.factor" } " file in it."
|
|
$terpri
|
|
"When a module takes the latter form, the directory containing the load file is termed the " { $emphasis "module directory" } "." ;
|
|
|
|
ARTICLE: "using-modules" "Using modules"
|
|
"To load " { $snippet "libs/concurrency" } " for instance, you simply issue the following command in the listener:"
|
|
{ $code "\"libs/concurrency\" require" }
|
|
"The " { $link require } " word will load all dependencies and source files of the " { $snippet "libs/concurrency" } " module."
|
|
{ $subsection require }
|
|
"Some modules are have a main entry point, and can be run much like an application in an operating system:"
|
|
{ $subsection run-module } ;
|
|
|
|
ARTICLE: "developing-modules" "Developing modules"
|
|
"To create a new module, you must first decide if the module is a single-file module or a directory with a load file; see " { $link "module-organization" } "."
|
|
$terpri
|
|
"If the module depends on other modules, the load file must first load them:"
|
|
{ $subsection POSTPONE: REQUIRES: }
|
|
"Then, it must define the module itself:"
|
|
{ $subsection POSTPONE: PROVIDE: }
|
|
"Finally, it can define a main entry point for use with " { $link run-module } ":"
|
|
{ $subsection POSTPONE: MAIN: }
|
|
"When working on a module, you can automatically reload any changed source files, in the correct order, without having to call " { $link run-file } " manually:"
|
|
{ $subsection reload-modules }
|
|
{ $subsection reset-modified }
|
|
{ $heading "Example " { $snippet "load.factor" } }
|
|
"Here is a simple module definition taken from " { $snippet "apps/tetris/load.factor" } "; it demonstrates all of the above features:"
|
|
{ $code "REQUIRES: libs/lazy-lists ;"
|
|
""
|
|
"PROVIDE: apps/tetris"
|
|
"{ +files+ {"
|
|
" \"tetris-colours.factor\""
|
|
" \"tetromino.factor\""
|
|
" \"tetris-piece.factor\""
|
|
" \"tetris-board.factor\""
|
|
" \"tetris.factor\""
|
|
" \"tetris-gl.factor\""
|
|
" \"tetris-gadget.factor\""
|
|
"} }"
|
|
"{ +tests+ {"
|
|
" \"test/tetris-piece.factor\""
|
|
" \"test/tetris-board.factor\""
|
|
" \"test/tetris.factor\""
|
|
"} } ;"
|
|
""
|
|
"USE: tetris-gadget"
|
|
""
|
|
"MAIN: apps/tetris tetris-window ;" } ;
|
|
|
|
ARTICLE: "testing-modules" "Unit testing modules"
|
|
"A unit test is a piece of code which starts with known input values, then compares the output of a word with an expected output, where the expected output is defined by the word's contract."
|
|
$terpri
|
|
"For example, if you were developing a word for computing symbolic derivatives, your unit tests would apply the word to certain input functions, comparing the results against the correct values. While the passing of these tests would not guarantee the algorithm is correct, it would at least ensure that what used to work keeps working, in that as soon as something breaks due to a change in another part of your program, failing tests will let you know."
|
|
$terpri
|
|
"Unit tests are placed in test harness files, separate from the rest of your source code. If the test harness needs to define words, they should be placed in the " { $snippet "temporary" } " vocabulary so that they can be forgotten after the tests have been run. Test harness files mainly consist of calls to the following two words:"
|
|
{ $subsection unit-test }
|
|
{ $subsection unit-test-fails }
|
|
{ $subsection assert-depth }
|
|
"Any non-trivial module should ship with unit tests in the " { $snippet "tests" } " subdirectory of the module directory. Unit test files should be listed in the " { $link +tests+ } " key of the " { $link POSTPONE: PROVIDE: } " form."
|
|
$terpri
|
|
"The following words run test harness files:"
|
|
{ $subsection test-module }
|
|
{ $subsection test-modules } ;
|
|
|
|
ARTICLE: "documenting-modules" "Documenting modules"
|
|
"Any non-trivial module should ship with documentation. Documentation " { $snippet ".facts" } " files should be listed along with your module's source files in the " { $link +files+ } " key passed to " { $link POSTPONE: PROVIDE: } ", and the main article should be referenced from the " { $link +help+ } " key."
|
|
$terpri
|
|
"Help markup is described in " { $link "writing-help" } ". Since help articles describing the core library have string names, a convention to avoid clashes is to name module help articles by arrays, where the first element is a string identifying the module, and the second identifies the article itself. For example, " { $snippet "{ \"concurrency\" \"processes\" }" } "." ;
|
|
|
|
ARTICLE: "submitting-modules" "Submitting modules"
|
|
"If you would like to contribute a module you wrote to Factor, please make sure of the following:"
|
|
{ $list
|
|
{ "The module actually is a module, and the load file has a " { $link POSTPONE: PROVIDE: } " form with the correct module name" }
|
|
{ "The module is placed in either the " { $snippet "apps/" } ", " { $snippet "libs/" } " or " { $snippet "demos/" } " directories" }
|
|
{ "The module is listed in the " { $snippet "README.txt" } " and " { $snippet "all.factor" } " files of its parent directory" }
|
|
"If the module is non-trivial, it should come with unit tests and documentation"
|
|
} ;
|
|
|
|
ARTICLE: "modules" "Modules and contributed libraries"
|
|
"The module system provides a set of conventions and tools for organizing large bodies of Factor code."
|
|
{ $subsection "module-organization" }
|
|
{ $subsection "using-modules" }
|
|
{ $subsection "developing-modules" }
|
|
{ $subsection "testing-modules" }
|
|
{ $subsection "documenting-modules" }
|
|
{ $subsection "submitting-modules" } ;
|