]> gitweb.factorcode.org Git - factor.git/blob - core/vocabs/parser/parser-docs.factor
merge project-euler.factor
[factor.git] / core / vocabs / parser / parser-docs.factor
1 USING: help.markup help.syntax parser strings words assocs vocabs ;
2 IN: vocabs.parser
3
4 ARTICLE: "word-search-errors"  "Word lookup errors"
5 "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."
6 $nl
7 "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."
8 $nl
9 "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."
10 $nl
11 "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."
12 { $subsections auto-use? } ;
13
14 ARTICLE: "word-search-syntax" "Syntax to control word lookup"
15 "Parsing words which make all words in a vocabulary available:"
16 { $subsections
17     POSTPONE: USE:
18     POSTPONE: USING:
19     POSTPONE: QUALIFIED:
20     POSTPONE: QUALIFIED-WITH:
21 }
22 "Parsing words which make a subset of all words in a vocabulary available:"
23 { $subsections
24     POSTPONE: FROM:
25     POSTPONE: EXCLUDE:
26     POSTPONE: RENAME:
27 }
28 "Removing vocabularies from the search path:"
29 { $subsections POSTPONE: UNUSE: }
30 "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."
31 { $subsections POSTPONE: IN: } ;
32
33 ARTICLE: "word-search-semantics" "Resolution of ambiguous word names"
34 "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."
35 $nl
36 "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."
37 { $subsections ambiguous-use-error }
38 "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."
39 $nl
40 "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."
41 $nl
42 "In practice, a small set of guidelines helps avoid name clashes:"
43 { $list
44   "Keep vocabularies small"
45   { "Hide internal words using " { $link POSTPONE: <PRIVATE } }
46   { "Make good use of " { $link POSTPONE: FROM: } ", " { $link POSTPONE: QUALIFIED: } " or " { $link POSTPONE: QUALIFIED-WITH: } }
47 } ;
48
49 ARTICLE: "word-search-private" "Private words"
50 "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."
51 { $subsections
52     POSTPONE: <PRIVATE
53     POSTPONE: PRIVATE>
54 } ;
55
56 ARTICLE: "word-search" "Parse-time word lookup"
57 "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."
58 $nl
59 "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."
60 { $subsections
61     "word-search-syntax"
62     "word-search-private"
63     "word-search-semantics"
64     "word-search-errors"
65 }
66 { $see-also "words" } ;
67
68 ARTICLE: "word-search-parsing" "Word lookup in parsing words"
69 "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."
70 $nl
71 "The current state used for word search is stored in a " { $emphasis "manifest" } ":"
72 { $subsections manifest }
73 "Words for working with the current manifest:"
74 { $subsections
75     use-vocab
76     unuse-vocab
77     add-qualified
78     add-words-from
79     add-words-excluding
80 }
81 "Words used to implement " { $link POSTPONE: IN: } ":"
82 { $subsections
83     current-vocab
84     set-current-vocab
85 }
86 "Words used to implement " { $link "word-search-private" } ":"
87 { $subsections
88     begin-private
89     end-private
90 } ;
91
92 ABOUT: "word-search"
93
94 HELP: manifest
95 { $var-description "The current manifest. Only set at parse time." }
96 { $class-description "Encapsulates the current vocabulary, as well as the vocabulary search path." } ;
97
98 HELP: <manifest>
99 { $values { "manifest" manifest } }
100 { $description "Creates a new manifest." } ;
101
102 HELP: set-current-vocab
103 { $values { "name" string } }
104 { $description "Sets the current vocabulary where new words will be defined, creating the vocabulary first if it does not exist." }
105 { $notes "This word is used to implement " { $link POSTPONE: IN: } "." } ;
106
107 HELP: no-current-vocab
108 { $error-description "Thrown when a new word is defined in a source file that does not have an " { $link POSTPONE: IN: } " form." } ;
109
110 HELP: current-vocab
111 { $values { "vocab" vocab } }
112 { $description "Returns the current vocabulary, where new words will be defined." }
113 { $errors "Throws an error if the current vocabulary has not been set." } ;
114
115 HELP: begin-private
116 { $description "Begins a block of private word definitions. Private word definitions are placed in the current vocabulary name, suffixed with " { $snippet ".private" } "." }
117 { $notes "This word is used to implement " { $link POSTPONE: <PRIVATE } "." } ;
118
119 HELP: end-private
120 { $description "Ends a block of private word definitions." }
121 { $notes "This word is used to implement " { $link POSTPONE: PRIVATE> } "." } ;
122
123 HELP: use-vocab
124 { $values { "vocab" "a vocabulary specifier" } }
125 { $description "Adds a vocabulary to the current manifest." }
126 { $notes "This word is used to implement " { $link POSTPONE: USE: } "." } ;
127
128 HELP: unuse-vocab
129 { $values { "vocab" "a vocabulary specifier" } }
130 { $description "Removes a vocabulary from the current manifest." }
131 { $notes "This word is used to implement " { $link POSTPONE: UNUSE: } "." } ;
132
133 HELP: add-qualified
134 { $values { "vocab" "a vocabulary specifier" } { "prefix" string } }
135 { $description "Adds the vocabulary's words, prefixed with the given string, to the current manifest." }
136 { $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." } ;
137
138 HELP: add-words-from
139 { $values { "vocab" "a vocabulary specifier" } { "words" "a sequence of word names" } }
140 { $description "Adds " { $snippet "words" } " from " { $snippet "vocab" } " to the current manifest." }
141 { $notes "This word is used to implement " { $link POSTPONE: FROM: } "." } ;
142
143 HELP: add-words-excluding
144 { $values { "vocab" "a vocabulary specifier" } { "words" "a sequence of word names" } }
145 { $description "Adds all words except for " { $snippet "words" } " from " { $snippet "vocab" } "  to the manifest." }
146 { $notes "This word is used to implement " { $link POSTPONE: EXCLUDE: } "." } ;
147
148 HELP: add-renamed-word
149 { $values { "word" string } { "vocab" "a vocabulary specifier" } { "new-name" string } }
150 { $description "Imports " { $snippet "word" } " from " { $snippet "vocab" } ", but renamed to " { $snippet "new-name" } "." }
151 { $notes "This word is used to implement " { $link POSTPONE: RENAME: } "." } ;
152
153 HELP: use-words
154 { $values { "assoc" assoc } }
155 { $description "Adds an assoc mapping word names to words to the current manifest." }
156 { $notes "This word is used by " { $link "locals" } " to implement lexically-scoped names." } ;
157
158 HELP: unuse-words
159 { $values { "assoc" assoc } }
160 { $description "Removes an assoc mapping word names to words from the current manifest." }
161 { $notes "This word is used by " { $link "locals" } " to implement lexically-scoped names." } ;
162
163 HELP: ambiguous-use-error
164 { $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: } "." } ;
165
166 HELP: search-manifest
167 { $values { "name" string } { "manifest" manifest } { "word/f" { $maybe word } } }
168 { $description "Searches for a word by name in the given manifest. If no such word could be found, outputs " { $link f } "." } ;
169
170 HELP: search
171 { $values { "name" string } { "word/f" { $maybe word } } }
172 { $description "Searches for a word by name in the current manifest. If no such word could be found, outputs " { $link f } "." }
173 $parsing-note ;