diff --git a/contrib/tetris/load.factor b/contrib/tetris/load.factor index 7a2a16fcd9..80e62252d3 100644 --- a/contrib/tetris/load.factor +++ b/contrib/tetris/load.factor @@ -11,6 +11,6 @@ PROVIDE: contrib/tetris { "test/tetris-piece.factor" "test/tetris-board.factor" "test/tetris.factor" } ; -USE: tetris +USE: tetris-gadget MAIN: contrib/tetris tetris-window ; diff --git a/doc/handbook/handbook.facts b/doc/handbook/handbook.facts index c116f1e56f..75155ebd9a 100644 --- a/doc/handbook/handbook.facts +++ b/doc/handbook/handbook.facts @@ -13,6 +13,9 @@ ARTICLE: "handbook" "Factor documentation" { $code "\"hello-world.factor\" run-file" } } { { "You can load modules from " { $snippet "contrib/" } " and " { $snippet "examples/" } " with " { $link require } ":" } { $code "\"contrib/httpd\" require" } } + { { "Some modules have a defined main entry point, and can be run just like applications in an operating system:" } + { $code "\"contrib/tetris\" run-module" } + } { { $link .s } " prints the contents of the stack." } { { $link . } " prints the object at the top of the stack." } { "If you are reading this from the Factor UI, take a look at " { $link "ui-tools" } "." } diff --git a/doc/handbook/tools.facts b/doc/handbook/tools.facts index 8d0b77e3a9..4d8879af22 100644 --- a/doc/handbook/tools.facts +++ b/doc/handbook/tools.facts @@ -56,24 +56,44 @@ $terpri 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/concurrency/" } " for instance, you simply issue the following command in the listener:" -{ $code "\"concurrency\" require" } -"The " { $link require } " word will load all dependencies and source files of the " { $snippet "concurrency" } " module." +"To load " { $snippet "contrib/concurrency" } " for instance, you simply issue the following command in the listener:" +{ $code "\"contrib/concurrency\" require" } +"The " { $link require } " word will load all dependencies and source files of the " { $snippet "contrib/concurrency" } " module." { $subsection require } -"To define a new module named " { $snippet "frob" } ", create one of the following two files:" +"Some modules are simply reusable libraries of code. Other modules are more like applications, and have a main entry point:" +{ $subsection run-module } +"To define a new module named " { $snippet "contrib/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:" +"Required 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:" +"Finally, if your module is an application, you can define a main entry point for " { $link run-module } ":" +{ $subsection POSTPONE: MAIN: } +"Here is a simple module definition taken from " { $snippet "contrib/tetris/load.factor" } ":" +{ $code "REQUIRES: contrib/lazy-lists ;" +"" +"PROVIDE: contrib/tetris {" +" \"tetris-colours.factor\"" +" \"tetromino.factor\"" +" \"tetris-piece.factor\"" +" \"tetris-board.factor\"" +" \"tetris.factor\"" +" \"tetris-gl.factor\"" +" \"tetris-gadget.factor\"" +"} {" +" \"test/tetris-piece.factor\"" +" \"test/tetris-board.factor\"" +" \"test/tetris.factor\"" +"} ;" +"" +"USE: tetris-gadget" +"" +"MAIN: contrib/tetris tetris-window ;" } +"The following words are useful during development of modules:" +{ $subsection reload-modules } { $subsection load-module } { $subsection test-module } ; diff --git a/library/modules.facts b/library/modules.facts index 98acd0ba23..03209e0786 100644 --- a/library/modules.facts +++ b/library/modules.facts @@ -41,3 +41,7 @@ HELP: test-module HELP: test-modules { $description "Runs unit test files for all loaded modules." } ; + +HELP: run-module +{ $values { "name" "a module name string" } } +{ $description "Runs the main entry point of the module, first loading the module if necessary using " { $link require } ". Entry points can be defined with the " { $link POSTPONE: MAIN: } " word." } ; diff --git a/library/syntax/parse-syntax.facts b/library/syntax/parse-syntax.facts index 065616d2ce..0c32ea7fa6 100644 --- a/library/syntax/parse-syntax.facts +++ b/library/syntax/parse-syntax.facts @@ -278,3 +278,8 @@ HELP: PROVIDE: { $syntax "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 its source files by calling " { $link provide } "." } ; + +HELP: MAIN: +{ $syntax "MAIN: name definition... ;" } +{ $values { "name" "a module name string" } { "definition" "an entry point definition" } } +{ $description "Registers a module entry point which can be run by passing the module name to " { $link run-module } "." } ;