1 USING: assocs continuations help.markup help.syntax parser sequences strings
5 ARTICLE: "word-search-errors" "Word lookup errors"
6 "If the parser cannot not find a word in the current vocabulary search path, it attempts to look for the word in all loaded vocabularies."
8 "If " { $link auto-use? } " mode is off, a restartable error is thrown with a restart for each vocabulary in question, together with a restart which defers the word in the current vocabulary, as if " { $link POSTPONE: DEFER: } " was used."
10 "If " { $link auto-use? } " mode is on and only one vocabulary has a word with this name, the vocabulary is added to the search path and parsing continues."
12 "If any restarts were invoked, or if " { $link auto-use? } " is on, the parser will print the correct " { $link POSTPONE: USING: } " after parsing completes. This form can be copy and pasted back into the source file."
13 { $subsections auto-use? } ;
15 ARTICLE: "word-search-syntax" "Syntax to control word lookup"
16 "Parsing words which make all words in a vocabulary available:"
21 POSTPONE: QUALIFIED-WITH:
23 "Parsing words which make a subset of all words in a vocabulary available:"
29 "Removing vocabularies from the search path:"
30 { $subsections POSTPONE: UNUSE: }
31 "In the listener, the " { $vocab-link "scratchpad" } " is the default vocabulary for new word definitions. In source files, there is no default vocabulary. Defining words before declaring a vocabulary with " { $link POSTPONE: IN: } " results in an error."
32 { $subsections POSTPONE: IN: } ;
34 ARTICLE: "word-search-semantics" "Resolution of ambiguous word names"
35 "There is a distinction between parsing words which perform “open” imports versus “closed” imports. An open import introduces all words from a vocabulary as identifiers, except possibly a finite set of exclusions. The " { $link POSTPONE: USE: } ", " { $link POSTPONE: USING: } " and " { $link POSTPONE: EXCLUDE: } " words perform open imports. A closed import only adds a fixed set of identifiers. The " { $link POSTPONE: FROM: } ", " { $link POSTPONE: RENAME: } ", " { $link POSTPONE: QUALIFIED: } " and " { $link POSTPONE: QUALIFIED-WITH: } " words perform closed imports. Note that the latter two are considered as closed imports, due to the fact that all identifiers they introduce are unambiguously qualified with a prefix. The " { $link POSTPONE: IN: } " parsing word also performs a closed import of the newly-created vocabulary."
37 "When the parser encounters a reference to a word, it first searches the closed imports, in order. Closed imports are searched from the most recent to least recent. If the word could not be found this way, it searches open imports. Unlike closed imports, with open imports, the order does not matter -- instead, if more than one vocabulary defines a word with this name, an error is thrown."
38 { $subsections ambiguous-use-error }
39 "To resolve the error, add a closed import, using " { $link POSTPONE: FROM: } ", " { $link POSTPONE: QUALIFIED: } " or " { $link POSTPONE: QUALIFIED-WITH: } ". The closed import will then take precedence over the open imports, and the ambiguity will be resolved."
41 "The rationale for this behavior is as follows. Open imports are named such because they are open to future extension; if a future version of a vocabulary that you use adds new words, those new words will now be in scope in your source file, too. To avoid problems, any references to the new word have to be resolved since the parser cannot safely determine which vocabulary was meant. This problem can be avoided entirely by using only closed imports, but this leads to additional verbosity."
43 "In practice, a small set of guidelines helps avoid name clashes:"
45 "Keep vocabularies small"
46 { "Hide internal words using " { $link POSTPONE: <PRIVATE } }
47 { "Make good use of " { $link POSTPONE: FROM: } ", " { $link POSTPONE: QUALIFIED: } " or " { $link POSTPONE: QUALIFIED-WITH: } }
50 ARTICLE: "word-search-private" "Private words"
51 "Words which only serve as implementation detail should be defined in a private code block. Words in a private code blocks get defined in a vocabulary whose name is the name of the current vocabulary suffixed with " { $snippet ".private" } ". Privacy is not enforced by the system; private words can be called from other vocabularies, and from the listener. However, this should be avoided where possible."
57 ARTICLE: "word-search" "Parse-time word lookup"
58 "When the parser reads a word name, it resolves the word at parse-time, looking up the " { $link word } " instance in the right vocabulary and adding it to the parse tree."
60 "Initially, only words from the " { $vocab-link "syntax" } " vocabulary are available in source files. Since most files will use words in other vocabularies, they will need to make those words available using a set of parsing words."
64 "word-search-semantics"
67 { $see-also "words" } ;
69 ARTICLE: "word-search-parsing" "Reflection support for vocabulary search path"
70 "The parsing words described in " { $link "word-search-syntax" } " are implemented using the below words, which you can also call from your own parsing words."
72 "The current state used for word search is stored in a " { $emphasis "manifest" } ":"
73 { $subsections manifest }
74 "Words for working with the current manifest:"
82 "Words used to implement " { $link POSTPONE: IN: } ":"
87 "Words used to implement " { $link "word-search-private" } ":"
96 { $var-description "The current manifest. Only set at parse time." }
97 { $class-description "Encapsulates the current vocabulary, as well as the vocabulary search path." } ;
100 { $values { "manifest" manifest } }
101 { $description "Creates a new manifest." } ;
103 HELP: <no-word-error>
105 { "name" "name of the missing words" }
106 { "possibilities" sequence }
108 { "restarts" sequence }
110 { $description "Creates a no word error." } ;
113 HELP: set-current-vocab
114 { $values { "name" string } }
115 { $description "Sets the current vocabulary where new words will be defined, creating the vocabulary first if it does not exist." }
116 { $notes "This word is used to implement " { $link POSTPONE: IN: } "." } ;
118 HELP: no-current-vocab
119 { $error-description "Thrown when a new word is defined in a source file that does not have an " { $link POSTPONE: IN: } " form." } ;
122 { $values { "vocab" vocab } }
123 { $description "Returns the current vocabulary, where new words will be defined." }
124 { $errors "Throws an error if the current vocabulary has not been set." } ;
127 { $description "Begins a block of private word definitions. Private word definitions are placed in the current vocabulary name, suffixed with " { $snippet ".private" } "." }
128 { $notes "This word is used to implement " { $link POSTPONE: <PRIVATE } "." } ;
131 { $description "Ends a block of private word definitions." }
132 { $notes "This word is used to implement " { $link POSTPONE: PRIVATE> } "." } ;
135 { $values { "vocab" "a vocabulary specifier" } }
136 { $description "Adds a vocabulary to the current manifest." }
137 { $notes "This word is used to implement " { $link POSTPONE: USE: } "." } ;
140 { $values { "vocab" "a vocabulary specifier" } }
141 { $description "Removes a vocabulary from the current manifest." }
142 { $notes "This word is used to implement " { $link POSTPONE: UNUSE: } "." } ;
145 { $values { "vocab" "a vocabulary specifier" } { "prefix" string } }
146 { $description "Adds the vocabulary's words, prefixed with the given string, to the current manifest." }
147 { $notes "If adding the vocabulary introduces ambiguity, the vocabulary will take precedence when resolving any ambiguous names. See the example in " { $link POSTPONE: QUALIFIED: } " for further explanation." } ;
150 { $values { "vocab" "a vocabulary specifier" } { "words" { $sequence "word names" } } }
151 { $description "Adds " { $snippet "words" } " from " { $snippet "vocab" } " to the current manifest." }
152 { $notes "This word is used to implement " { $link POSTPONE: FROM: } "." } ;
154 HELP: add-words-excluding
155 { $values { "vocab" "a vocabulary specifier" } { "words" { $sequence "word names" } } }
156 { $description "Adds all words except for " { $snippet "words" } " from " { $snippet "vocab" } " to the manifest." }
157 { $notes "This word is used to implement " { $link POSTPONE: EXCLUDE: } "." } ;
159 HELP: add-renamed-word
160 { $values { "word" string } { "vocab" "a vocabulary specifier" } { "new-name" string } }
161 { $description "Imports " { $snippet "word" } " from " { $snippet "vocab" } ", but renamed to " { $snippet "new-name" } "." }
162 { $notes "This word is used to implement " { $link POSTPONE: RENAME: } "." } ;
165 { $values { "assoc" assoc } }
166 { $description "Adds an assoc mapping word names to words to the current manifest." } ;
169 { $values { "assoc" assoc } }
170 { $description "Removes an assoc mapping word names to words from the current manifest." } ;
172 HELP: ambiguous-use-error
173 { $error-description "Thrown when a word name referenced in source file is available in more than one vocabulary in the manifest. Such cases must be explicitly disambiguated using " { $link POSTPONE: FROM: } ", " { $link POSTPONE: EXCLUDE: } ", " { $link POSTPONE: QUALIFIED: } ", or " { $link POSTPONE: QUALIFIED-WITH: } "." } ;
175 HELP: search-manifest
176 { $values { "name" string } { "manifest" manifest } { "word/f" { $maybe word } } }
177 { $description "Searches for a word by name in the given manifest. If no such word could be found, outputs " { $link f } "." } ;
180 { $values { "name" string } { "word/f" { $maybe word } } }
181 { $description "Searches for a word by name in the current manifest. If no such word could be found, outputs " { $link f } "." }