]> gitweb.factorcode.org Git - factor.git/blob - core/vocabs/parser/parser-docs.factor
Use $sequence in a few places.
[factor.git] / core / vocabs / parser / parser-docs.factor
1 USING: assocs continuations help.markup help.syntax parser sequences strings
2 words vocabs ;
3 IN: vocabs.parser
4
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."
7 $nl
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."
9 $nl
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."
11 $nl
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? } ;
14
15 ARTICLE: "word-search-syntax" "Syntax to control word lookup"
16 "Parsing words which make all words in a vocabulary available:"
17 { $subsections
18     POSTPONE: USE:
19     POSTPONE: USING:
20     POSTPONE: QUALIFIED:
21     POSTPONE: QUALIFIED-WITH:
22 }
23 "Parsing words which make a subset of all words in a vocabulary available:"
24 { $subsections
25     POSTPONE: FROM:
26     POSTPONE: EXCLUDE:
27     POSTPONE: RENAME:
28 }
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: } ;
33
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."
36 $nl
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."
40 $nl
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."
42 $nl
43 "In practice, a small set of guidelines helps avoid name clashes:"
44 { $list
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: } }
48 } ;
49
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."
52 { $subsections
53     POSTPONE: <PRIVATE
54     POSTPONE: PRIVATE>
55 } ;
56
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."
59 $nl
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."
61 { $subsections
62     "word-search-syntax"
63     "word-search-private"
64     "word-search-semantics"
65     "word-search-errors"
66 }
67 { $see-also "words" } ;
68
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."
71 $nl
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:"
75 { $subsections
76     use-vocab
77     unuse-vocab
78     add-qualified
79     add-words-from
80     add-words-excluding
81 }
82 "Words used to implement " { $link POSTPONE: IN: } ":"
83 { $subsections
84     current-vocab
85     set-current-vocab
86 }
87 "Words used to implement " { $link "word-search-private" } ":"
88 { $subsections
89     begin-private
90     end-private
91 } ;
92
93 ABOUT: "word-search"
94
95 HELP: manifest
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." } ;
98
99 HELP: <manifest>
100 { $values { "manifest" manifest } }
101 { $description "Creates a new manifest." } ;
102
103 HELP: <no-word-error>
104 { $values
105   { "name" "name of the missing words" }
106   { "possibilities" sequence }
107   { "error" error }
108   { "restarts" sequence }
109 }
110 { $description "Creates a no word error." } ;
111
112
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: } "." } ;
117
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." } ;
120
121 HELP: current-vocab
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." } ;
125
126 HELP: begin-private
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 } "." } ;
129
130 HELP: end-private
131 { $description "Ends a block of private word definitions." }
132 { $notes "This word is used to implement " { $link POSTPONE: PRIVATE> } "." } ;
133
134 HELP: use-vocab
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: } "." } ;
138
139 HELP: unuse-vocab
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: } "." } ;
143
144 HELP: add-qualified
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." } ;
148
149 HELP: add-words-from
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: } "." } ;
153
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: } "." } ;
158
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: } "." } ;
163
164 HELP: use-words
165 { $values { "assoc" assoc } }
166 { $description "Adds an assoc mapping word names to words to the current manifest." } ;
167
168 HELP: unuse-words
169 { $values { "assoc" assoc } }
170 { $description "Removes an assoc mapping word names to words from the current manifest." } ;
171
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: } "." } ;
174
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 } "." } ;
178
179 HELP: search
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 } "." }
182 $parsing-note ;