1 USING: help.markup help.syntax kernel sequences words
2 math strings vectors quotations generic effects classes
3 vocabs.loader definitions io vocabs source-files
4 quotations namespaces ;
7 ARTICLE: "vocabulary-search-shadow" "Shadowing word names"
8 "If adding a vocabulary to the search path results in a word in another vocabulary becoming inaccessible due to the new vocabulary defining a word with the same name, a message is printed to the " { $link stdio } " stream. Except when debugging suspected name clashes, these messages can be ignored."
10 "Here is an example where shadowing occurs:"
13 "USING: sequences io ;"
16 " #! Prints a message, then calls sequences::append."
17 " \"foe::append calls sequences::append\" print append ;"
22 " #! Infinite recursion! Calls fee::append."
23 " \"fee::append calls fee::append\" print append ;"
28 " #! Redefining fee::append to call foe::append."
29 " \"fee::append calls foe::append\" print append ;"
31 "\"1234\" \"5678\" append print"
33 "When placed in a source file and run, the above code produces the following output:"
35 "fee::append calls foe::append"
36 "foe::append calls sequences::append"
40 ARTICLE: "vocabulary-search-errors" "Word lookup errors"
41 "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. Then, one of three things happen:"
43 { "If there are no words having this name at all, an error is thrown and parsing stops." }
44 { "If there is exactly one vocabulary having a word with this name, the vocabulary is automatically added to the search path. This behavior is intended for interactive use and exploratory programming only, and production code should contain full " { $link POSTPONE: USING: } " declarations." }
45 { "If there is more than one vocabulary which contains a word with this name, a restartable error is thrown, with a restart for each vocabulary in question. The restarts add the vocabulary to the search path and continue parsing." }
47 "When writing a new vocabulary, one approach is to ignore " { $link POSTPONE: USING: } " declarations altogether, then to load the vocabulary and observe any parser notes and restarts and use this information to write the correct " { $link POSTPONE: USING: } " declaration." ;
49 ARTICLE: "vocabulary-search" "Vocabulary search"
50 "When the parser reads a token, it attempts to look up a word named by that token. The lookup is performed by searching each vocabulary in the search path, in order."
52 "For a source file the vocabulary search path starts off with two vocabularies:"
53 { $code "syntax\nscratchpad" }
54 "The " { $vocab-link "syntax" } " vocabulary consists of a set of parsing words for reading Factor data and defining new words. The " { $vocab-link "scratchpad" } " vocabulary is the default vocabulary for new word definitions."
56 "At the interactive listener, the default search path contains many more vocabularies. Details on the default search path and parser invocation are found in " { $link "parser" } "."
58 "Three parsing words deal with the vocabulary search path:"
59 { $subsection POSTPONE: USE: }
60 { $subsection POSTPONE: USING: }
61 { $subsection POSTPONE: IN: }
62 "Private words can be defined; note that this is just a convention and they can be called from other vocabularies anyway:"
63 { $subsection POSTPONE: <PRIVATE }
64 { $subsection POSTPONE: PRIVATE> }
65 { $subsection "vocabulary-search-errors" }
66 { $subsection "vocabulary-search-shadow" }
67 { $see-also "words" } ;
69 ARTICLE: "reading-ahead" "Reading ahead"
70 "Parsing words can consume input:"
72 { $subsection scan-word }
73 "For example, the " { $link POSTPONE: HEX: } " word uses this feature to read hexadecimal literals:"
74 { $see POSTPONE: HEX: }
75 "It is defined in terms of a lower-level word that takes the numerical base on the data stack, but reads the number from the parser and then adds it to the parse tree:"
77 "Another simple example is the " { $link POSTPONE: \ } " word:"
78 { $see POSTPONE: \ } ;
80 ARTICLE: "parsing-word-nest" "Nested structure"
81 "Recall that the parser loop calls parsing words with an accumulator vector on the stack. The parser loop can be invoked recursively with a new, empty accumulator; the result can then be added to the original accumulator. This is how parsing words for object literals are implemented; object literals can nest arbitrarily deep."
83 "A simple example is the parsing word that reads a quotation:"
85 "This word uses a utility word which recursively invokes the parser, reading objects into a new accumulator until an occurrence of " { $link POSTPONE: ] } ":"
86 { $subsection parse-literal }
87 "There is another, lower-level word for reading nested structure, which is also useful when called directly:"
88 { $subsection parse-until }
89 "Words such as " { $link POSTPONE: ] } " use a declaration which causes them to throw an error when an unpaired occurrence is encountered:"
90 { $subsection POSTPONE: delimiter }
91 { $see-also POSTPONE: { POSTPONE: H{ POSTPONE: V{ POSTPONE: W{ POSTPONE: T{ POSTPONE: } } ;
93 ARTICLE: "defining-words" "Defining words"
94 "Defining words add definitions to the dictionary without modifying the parse tree. The simplest example is the " { $link POSTPONE: SYMBOL: } " word."
95 { $see POSTPONE: SYMBOL: }
96 "The key factor in the definition of " { $link POSTPONE: SYMBOL: } " is " { $link CREATE } ", which reads a token from the input and creates a word with that name. This word is then passed to " { $link define-symbol } "."
97 { $subsection CREATE }
98 "Colon definitions are defined in a more elaborate way:"
99 { $subsection POSTPONE: : }
100 "The " { $link POSTPONE: : } " word first calls " { $link CREATE } ", and then reads input until reaching " { $link POSTPONE: ; } " using a utility word:"
101 { $subsection parse-definition }
102 "The " { $link POSTPONE: ; } " word is just a delimiter; an unpaired occurrence throws a parse error:"
104 "There are additional parsing words whose syntax is delimited by " { $link POSTPONE: ; } ", and they are all implemented by calling " { $link parse-definition } "." ;
106 ARTICLE: "parsing-tokens" "Parsing raw tokens"
107 "So far we have seen how to read individual tokens, or read a sequence of parsed objects until a delimiter. It is also possible to read raw tokens from the input and perform custom processing."
109 "One example is the " { $link POSTPONE: USING: } " parsing word."
110 { $see POSTPONE: USING: }
111 "It reads a list of vocabularies terminated by " { $link POSTPONE: ; } ". However, the vocabulary names do not name words, except by coincidence; so " { $link parse-until } " cannot be used here. Instead, a lower-level word is called:"
112 { $subsection parse-tokens } ;
114 ARTICLE: "parsing-words" "Parsing words"
115 "The Factor parser is follows a simple recursive-descent design. The parser reads successive tokens from the input; if the token identifies a number or an ordinary word, it is added to an accumulator vector. Otherwise if the token identifies a parsing word, the parsing word is executed immediately."
117 "Parsing words are marked by suffixing the definition with a " { $link POSTPONE: parsing } " declaration. Here is the simplest possible parsing word; it prints a greeting at parse time:"
118 { $code ": hello \"Hello world\" print ; parsing" }
119 "Parsing words must have stack effect " { $snippet "( accum -- accum )" } ", where " { $snippet "accum" } " is the accumulator vector supplied by the parser. Parsing words can read input, add word definitions to the dictionary, and do anything an ordinary word can."
121 "Tools for implementing parsing words:"
122 { $subsection "reading-ahead" }
123 { $subsection "parsing-word-nest" }
124 { $subsection "defining-words" }
125 { $subsection "parsing-tokens" } ;
127 ARTICLE: "parser-lexer" "The lexer"
128 "Two variables that encapsulate internal parser state:"
130 { $subsection lexer }
131 "Creating a default lexer:"
132 { $subsection <lexer> }
133 "A word to test of the end of input has been reached:"
134 { $subsection still-parsing? }
135 "A word to get the text of the current line:"
136 { $subsection line-text }
137 "A word to advance the lexer to the next line:"
138 { $subsection next-line }
139 "Two generic words to override the lexer's token boundary detection:"
140 { $subsection skip-blank }
141 { $subsection skip-word }
142 "A utility used when parsing string literals:"
143 { $subsection parse-string }
144 "The parser can be invoked with a custom lexer:"
145 { $subsection (parse-lines) }
146 { $subsection with-parser } ;
148 ARTICLE: "parser-files" "Parsing source files"
149 "The parser can run source files:"
150 { $subsection run-file }
151 { $subsection parse-file }
152 { $subsection bootstrap-file }
153 "The parser cross-references source files and definitions. This allows it to keep track of removed definitions, and prevent forward references and accidental redefinitions."
155 "When a source file is reloaded, the parser compares the previous list of definitions with the current list; any definitions which are no longer present in the file are removed by a call to " { $link forget } ". A warning message is printed if any other definitions still depend on the removed definitions."
157 "The parser also catches forward references when reloading source files. This is best illustrated with an example. Suppose we load a source file " { $snippet "a.factor" } ":"
159 "USING: io sequences ;"
161 ": hello \"Hello\" ;"
162 ": world \"world\" ;"
163 ": hello-world hello " " world 3append print ;"
165 "The definitions for " { $snippet "hello" } ", " { $snippet "world" } ", and " { $snippet "hello-world" } " are in the dictionary."
167 "Now, after some heavily editing and refactoring, the file looks like this:"
169 "USING: namespaces ;"
171 ": hello \"Hello\" % ;"
172 ": hello-world [ hello " " % world ] \"\" make ;"
173 ": world \"world\" % ;"
175 "Note that the developer has made a mistake, placing the definition of " { $snippet "world" } " " { $emphasis "after" } " its usage in " { $snippet "hello-world" } "."
177 "If the parser did not have special checks for this case, then the modified source file would still load, because when the definition of " { $snippet "hello-world" } " on line 4 is being parsed, the " { $snippet "world" } " word is already present in the dictionary from an earlier run. The developer would then not discover this mistake until attempting to load the source file into a fresh image."
179 "Since this is undesirable, the parser explicitly raises an error if a source file refers to a word which is in the dictionary, but defined after it is used."
180 { $subsection forward-error }
181 "If a source file raises a " { $link forward-error } " when loaded into a development image, then it would have raised a " { $link no-word } " error when loaded into a fresh image."
183 "The parser also catches duplicate definitions. If an artifact is defined twice in the same source file, the earlier definition will never be accessible, and this is almost always a mistake, perhaps due to a bad choice of word names, or a copy and paste error. The parser raises an error in this case."
184 { $subsection redefine-error }
185 { $see-also "source-files" } ;
187 ARTICLE: "parser-usage" "Reflective parser usage"
188 "The parser can be called on a string:"
190 { $subsection parse }
191 { $subsection parse-fresh }
192 "The parser can also parse from a stream:"
193 { $subsection parse-stream } ;
195 ARTICLE: "parser" "The parser"
196 "This parser is a general facility for reading textual representations of objects and definitions. The parser is implemented in the " { $vocab-link "parser" } " and " { $vocab-link "syntax" } " vocabularies."
198 "This section concerns itself with usage and extension of the parser. Standard syntax is described in " { $link "syntax" } "."
199 { $subsection "vocabulary-search" }
200 { $subsection "parser-files" }
201 { $subsection "parser-usage" }
202 "The parser can be extended."
203 { $subsection "parsing-words" }
204 { $subsection "parser-lexer" } ;
210 "This word should only be called from parsing words."
214 { $var-description "Stores the current " { $link lexer } " instance." }
215 { $class-description "An object for tokenizing parser input. It has the following slots:"
217 { { $link lexer-text } " - the lines being parsed; an array of strings" }
218 { { $link lexer-line } " - the line number being parsed; unlike most indices this is 1-based for friendlier error reporting and integration with text editors" }
219 { { $link lexer-column } " - the current column position, zero-based" }
221 "Custom lexing can be implemented by delegating a tuple to an instance of this class and implementing the " { $link skip-word } " and " { $link skip-blank } " generic words." } ;
224 { $values { "text" "a sequence of strings" } { "lexer" lexer } }
225 { $description "Creates a new lexer for tokenizing the given sequence of lines." } ;
228 { $values { "loc" "a " { $snippet "{ path line# }" } " pair" } }
229 { $description "Outputs the current parser location. This value can be passed to " { $link set-where } " or " { $link (save-location) } "." } ;
232 { $values { "definition" "a definition specifier" } }
233 { $description "Throws a " { $link redefine-error } "." }
234 { $error-description "Indicates that a single source file contains two definitions for the same artifact, one of which shadows the other. This is an error since it indicates a likely mistake, such as two words accidentally named the same by the developer; the error is restartable." } ;
237 { $values { "definition" "a definition specifier" } { "?" "a boolean" } }
238 { $description "Tests if this definition is already present in the current source file." }
241 HELP: (save-location)
242 { $values { "definition" "a definition specifier" } { "loc" "a " { $snippet "{ path line# }" } " pair" } }
243 { $description "Saves the location of a definition and associates this definition with the current source file."
245 "This is the book-keeping required to detect " { $link redefine-error } " and " { $link forward-error } "." } ;
248 { $values { "definition" "a definition specifier" } }
249 { $description "Saves the location of a definition and associates this definition with the current source file."
251 "This is the book-keeping required to detect " { $link redefine-error } " and " { $link forward-error } "." } ;
254 { $var-description "A boolean controlling whether the parser will print various notes and warnings. Switched on by default. If a source file is being run for its effect on the " { $link stdio } " stream, this variable should be switched off, to prevent parser notes from polluting the output." } ;
257 { $values { "?" "a boolean" } }
258 { $description "Tests if the parser will print various notes and warnings. To disable parser notes, either set " { $link parser-notes } " to " { $link f } ", or pass the " { $snippet "-quiet" } " command line switch." } ;
261 { $values { "lexer" lexer } }
262 { $description "Advances the lexer to the next input line, discarding the remainder of the current line." } ;
265 { $var-description "Stores the " { $link source-file } " being parsed. The " { $link source-file-path } " of this object comes from the input parameter to " { $link parse-stream } "." } ;
267 HELP: old-definitions
268 { $var-description "Stores an assoc where the keys form the set of definitions which were defined by " { $link file } " the most recent time it was loaded." } ;
270 HELP: new-definitions
271 { $var-description "Stores an assoc where the keys form the set of definitions which were defined so far by the current parsing of " { $link file } "." } ;
274 { $error-description "Thrown when the parser encounters invalid input. A parse error wraps an underlying error and holds the file being parsed, line number, and column number." } ;
277 { $values { "msg" "an error" } { "error" parse-error } }
278 { $description "Creates a new " { $link parse-error } ", filling in the location information from the current " { $link lexer } "." } ;
281 { $values { "lexer" lexer } { "str" string } }
282 { $description "Outputs the text of the line being parsed." } ;
285 { $values { "i" "a starting index" } { "seq" "a sequence" } { "quot" "a quotation with stack effect " { $snippet "( elt -- ? )" } } { "n" integer } }
286 { $description "Variant of " { $link find* } " that outputs the length of the sequence instead of " { $link f } " if no elements satisfy the predicate." } ;
289 { $values { "lexer" lexer } { "quot" "a quotation with stack effect " { $snippet "( col line -- newcol )" } } }
290 { $description "Applies a quotation to the current column and line text to produce a new column, and moves the lexer position." } ;
293 { $values { "lexer" lexer } }
294 { $contract "Skips whitespace characters." }
295 { $notes "Custom lexers can implement this generic word." } ;
298 { $values { "lexer" lexer } }
300 "Skips until the end of the current token."
302 "The default implementation treats a single " { $snippet "\"" } " as a word by itself; otherwise it searches forward until a whitespace character or the end of the line."
304 { $notes "Custom lexers can implement this generic word." } ;
306 HELP: still-parsing-line?
307 { $values { "lexer" lexer } { "?" "a boolean" } }
308 { $description "Outputs " { $link f } " if the end of the current line has been reached, " { $link t } " otherwise." } ;
311 { $values { "lexer" lexer } { "str/f" "a " { $link string } " or " { $link f } } }
312 { $description "Reads the next token from the lexer. Tokens are delimited by whitespace, with the exception that " { $snippet "\"" } " is treated like a single token even when not followed by whitespace." } ;
315 { $values { "str/f" "a " { $link string } " or " { $link f } } }
316 { $description "Reads the next token from the lexer. See " { $link parse-token } " for details." }
320 { $error-description "Indicates the parser encountered an invalid escape code following a backslash (" { $snippet "\\" } ") in a string literal. See " { $link "escape" } " for a list of valid escape codes." } ;
323 { $error-description "Indicates the parser encountered an invalid numeric literal." } ;
326 { $values { "escape" "a single-character escape" } { "ch" "a character" } }
327 { $description "Converts from a single-character escape code and the corresponding character." }
328 { $examples { $example "CHAR: n escape CHAR: \\n = ." "t" } } ;
331 { $values { "m" "an index into " { $snippet "str" } } { "str" string } { "n" "an index into " { $snippet "str" } } { "ch" "a character" } }
332 { $description "Helper word for " { $link parse-string } " which parses an escape sequence starting at the " { $snippet "m" } "th index of " { $snippet "str" } "." }
333 { $errors "Throws a " { $link bad-escape } " if the string contains an invalid escape sequence." } ;
336 { $values { "m" "an index into " { $snippet "str" } } { "str" string } { "n" "an index into " { $snippet "str" } } { "ch" "a character" } }
337 { $description "Helper word for " { $link parse-string } " which parses a character starting at the " { $snippet "m" } "th index of " { $snippet "str" } "." } ;
340 { $values { "str" "a new " { $link string } } }
341 { $description "Parses the line until a quote (\"), interpreting escape codes along the way." }
342 { $errors "Throws an " { $link bad-escape } " if the string contains an invalid escape sequence." }
346 { $values { "lexer" lexer } { "?" "a boolean" } }
347 { $description "Outputs " { $link f } " if end of input has been reached, " { $link t } " otherwise." } ;
350 { $var-description "A variable holding the current vocabulary search path as a sequence of assocs." } ;
352 { use in use+ (use+) set-use set-in POSTPONE: USING: POSTPONE: USE: file-vocabs } related-words
355 { $var-description "A variable holding the name of the current vocabulary for new definitions." } ;
357 HELP: shadow-warnings
358 { $values { "vocab" "an assoc mapping strings to words" } { "vocabs" "a sequence of assocs" } }
359 { $description "Tests if any keys in " { $snippet "vocab" } " shadow keys in the elements of " { $snippet "vocabs" } ", and if so, prints a warning message. These warning messages can be disabled by setting " { $link parser-notes } " to " { $link f } "." } ;
362 { $values { "vocab" "an assoc mapping strings to words" } }
363 { $description "Adds an assoc at the front of the search path." }
367 { $values { "vocab" string } }
368 { $description "Adds a new vocabulary at the front of the search path after loading it if necessary. Subsequent word lookups by the parser will search this vocabulary first." }
370 { $errors "Throws an error if the vocabulary does not exist." } ;
373 { $values { "seq" "a sequence of strings" } }
374 { $description "Sets the vocabulary search path. Later vocabularies take precedence." }
375 { $errors "Throws an error if one of the vocabularies does not exist." }
379 { $values { "seq" "a sequence of strings" } }
380 { $description "Adds multiple vocabularies to the search path, with later vocabularies taking precedence." }
381 { $errors "Throws an error if one of the vocabularies does not exist." }
385 { $values { "name" string } }
386 { $description "Sets the current vocabulary where new words will be defined, creating the vocabulary first if it does not exist." }
390 { $values { "string" "a word name" } { "word" "a new word" } }
391 { $description "Creates a word in the current vocabulary. Until re-defined, the word throws an error when invoked." }
395 { $values { "end" string } { "seq" "a new sequence of strings" } }
396 { $description "Reads a sequence of tokens until the first occurrence of " { $snippet "end" } ". The tokens remain as strings and are not processed in any way." }
397 { $examples "This word is used to implement " { $link POSTPONE: USING: } "." }
401 { $values { "word" word } }
402 { $description "Reads the next token from the line currently being parsed, and creates a word with that name in the current vocabulary." }
403 { $errors "Throws an error if the end of the line is reached." }
407 { $values { "name" string } { "newword" word } }
408 { $description "Throws a " { $link no-word } " error." }
409 { $error-description "Thrown if the parser encounters a token which does not name a word in the current vocabulary search path. If any words with this name exist in vocabularies not part of the search path, a number of restarts will offer to add those vocabularies to the search path and use the chosen word." }
410 { $notes "Apart from a missing " { $link POSTPONE: USE: } ", this error can also indicate an ordering issue. In Factor, words must be defined before they can be called. Mutual recursion can be implemented via " { $link POSTPONE: DEFER: } "." } ;
413 { $values { "str" string } { "word" word } }
414 { $description "Searches for a word by name in the current vocabulary search path. If no such word could be found, throws a " { $link no-word } " error. If the search path does not contain a word with this name but other vocabularies do, the error will have restarts offering to add vocabularies to the search path." }
418 { $values { "word" word } }
419 { $description "Throws a " { $link forward-error } "." }
420 { $description "Indicates a word is being referenced prior to the location of its most recent definition. This can only happen if a source file is loaded, and subsequently edited such that two dependent definitions are reversed." } ;
423 { $values { "word/number/f" "a word, number or " { $link f } } }
424 { $description "Reads the next token from parser input. If the token is a valid number literal, it is converted to a number, otherwise the dictionary is searched for a word named by the token. Outputs " { $link f } " if the end of the input has been reached." }
425 { $errors "Throws an error if the token does not name a word, and does not parse as a number." }
429 { $values { "want" "a " { $link word } " or " { $link f } } { "got" word } }
430 { $description "Throws an " { $link unexpected } " error." }
431 { $error-description "Thrown by the parser if an unmatched closing delimiter is encountered." }
433 "Parsing the following snippet will throw this error:"
434 { $code "[ 1 2 3 }" }
438 { $values { "word" "a " { $link word } } }
439 { $description "Throws an " { $link unexpected } " error indicating the parser was looking for an occurrence of " { $snippet "word" } " but encountered end of file." } ;
442 { $values { "accum" vector } { "end" word } { "?" "a boolean" } }
443 { $description "Parses a token. If the token is a number or an ordinary word, it is added to the accumulator. If it is a parsing word, calls the parsing word with the accumulator on the stack. Outputs " { $link f } " if " { $snippet "end" } " is encountered, " { $link t } " otherwise." }
447 { $values { "accum" vector } { "end" word } }
448 { $description "Parses objects from parser input until " { $snippet "end" } " is encountered, adding them to the accumulator." }
452 { $values { "end" word } { "vec" "a new vector" } }
453 { $description "Parses objects from parser input until " { $snippet "end" } ". Outputs a new vector with the results." }
454 { $examples "This word is used to implement " { $link POSTPONE: ARTICLE: } "." }
457 { parse-tokens (parse-until) parse-until } related-words
460 { $values { "accum" vector } { "obj" object } }
461 { $description "Convenience word for parsing words. It behaves exactly the same as " { $link push } ", except the accumulator remains on the stack." }
465 { $values { "lexer" lexer } { "quot" "a quotation with stack effect " { $snippet "( -- accum )" } } { "newquot" "a new " { $link quotation } } }
466 { $description "Sets up the parser and calls the quotation. The quotation can make use of parsing words such as " { $link scan } " and " { $link parse-until } ". It must yield a sequence, which is converted to a quotation and output. Any errors thrown by the quotation are wrapped in parse errors." } ;
469 { $values { "lexer" lexer } { "quot" "a new " { $link quotation } } }
470 { $description "Parses Factor source code using a custom lexer. The vocabulary search path is taken from the current scope." }
471 { $errors "Throws a " { $link parse-error } " if the input is malformed." } ;
474 { $values { "lines" "a sequence of strings" } { "quot" "a new " { $link quotation } } }
475 { $description "Parses Factor source code which has been tokenized into lines. The vocabulary search path is taken from the current scope." }
476 { $errors "Throws a " { $link parse-error } " if the input is malformed." } ;
479 { $var-description "A variable holding a quotation with stack effect " { $snippet "( lines -- lexer )" } ". This quotation is called by the parser to create " { $link lexer } " instances. This variable can be rebound to a quotation which outputs a custom tuple delegating to " { $link lexer } " to customize syntax." } ;
482 { $values { "effect" "an instance of " { $link effect } } }
483 { $description "Parses a stack effect from the current input line." }
484 { $examples "This word is used by " { $link POSTPONE: ( } " to parse stack effect declarations." }
488 { $values { "base" "an integer between 2 and 36" } { "parsed" integer } }
489 { $description "Reads an integer in a specific numerical base from the parser input." }
493 { $values { "accum" vector } { "end" word } { "quot" "a quotation with stack effect " { $snippet "( seq -- obj )" } } }
494 { $description "Parses objects from parser input until " { $snippet "end" } ", applies the quotation to the resulting sequence, and adds the output value to the accumulator." }
495 { $examples "This word is used to implement " { $link POSTPONE: C{ } "." }
498 HELP: parse-definition
499 { $values { "quot" "a new " { $link quotation } } }
500 { $description "Parses objects from parser input until " { $link POSTPONE: ; } " and outputs a quotation with the results." }
501 { $examples "This word is used to implement " { $link POSTPONE: : } "." }
504 HELP: bootstrap-syntax
505 { $var-description "Only set during bootstrap. Stores a copy of the " { $link vocab-words } " of the host's syntax vocabulary; this allows the host's parsing words to be used during bootstrap source parsing, not the target's." } ;
508 { $description "Installs the initial the vocabulary search path for parsing a file. This consists of the " { $snippet "syntax" } " vocabulary together with the " { $snippet "scratchpad" } " vocabulary." } ;
511 { $values { "str" string } { "quot" quotation } }
512 { $description "Parses Factor source code from a string. The current vocabulary search path is used." }
513 { $errors "Throws a parse error if the input is malformed." } ;
516 { $values { "lines" "a sequence of strings" } { "quot" quotation } }
517 { $description "Parses Factor source code in a sequence of lines. The initial vocabulary search path is used (see " { $link file-vocabs } ")." }
518 { $errors "Throws a parse error if the input is malformed." } ;
521 { $values { "str" string } }
522 { $description "Parses Factor source code from a string, and calls the resulting quotation. The current vocabulary search path is used." }
523 { $errors "Throws an error if the input is malformed, or if the quotation throws an error." } ;
526 { $var-description "A quotation called by " { $link parse-stream } " after parsing the input stream. The default value recompiles new word definitions; see " { $link "recompile" } " for details." } ;
528 { parse-hook no-parse-hook } related-words
531 { $values { "quot" "a quotation" } }
532 { $description "Runs the quotation in a new dynamic scope where " { $link parse-hook } " is set to " { $link f } ", then calls the outer " { $link parse-hook } " after the quotation returns. This has the effect of postponing any recompilation to the end of a quotation." } ;
535 { $values { "stream" "an input stream" } { "name" "a pathname string" } }
536 { $description "Prepares to parse a source file by reading the entire contents of the stream and setting some variables. The pathname identifies the stream for cross-referencing purposes." }
537 { $errors "Throws an I/O error if there was an error reading from the stream." }
538 { $notes "This is one of the factors of " { $link parse-stream } "." } ;
541 { $values { "seq" "a sequence of definitions" } { "usages" "an association list mapping definitions to sequences of definitions" } }
542 { $description "Outputs an association list mapping elements of " { $snippet "seq" } " to lists of usages which exclude the definitions in " { $snippet "seq" } " themselves." } ;
545 { $values { "assoc" "an assoc where the keys are definitions" } { "newassoc" "an assoc where the keys are definitions" } }
546 { $description "Removes all definitions from the assoc which are no longer present in the current " { $link file } "." } ;
549 { $values { "usages" "a sequence of definitions which reference removed definitions" } { "referenced" "a sequence of definitions removed from this source file which are still referenced elsewhere" } { "removed" "a sequence of definitions removed from this source file" } }
550 { $description "Collects information about changed word definitioins after parsing." } ;
553 { $description "Forgets removed definitions and prints a warning message if any of them are still referenced from other source files." } ;
555 HELP: record-definitions
556 { $values { "file" source-file } }
557 { $description "Records that all " { $link new-definitions } " were defined in " { $snippet "file" } "." } ;
560 { $values { "quot" "the quotation just parsed" } }
561 { $description "Records information to the current " { $link file } " and prints warnings about any removed definitions which are still in use." }
562 { $notes "This is one of the factors of " { $link parse-stream } "." } ;
565 { $description "Records information to the current " { $link file } " after an incomplete parse which ended with an error." } ;
568 { $values { "stream" "an input stream" } { "name" "a file name for error reporting and cross-referencing" } { "quot" quotation } }
569 { $description "Parses Factor source code read from the stream. The initial vocabulary search path is used." }
570 { $errors "Throws an I/O error if there was an error reading from the stream. Throws a parse error if the input is malformed." } ;
573 { $values { "file" "a pathname string" } { "quot" quotation } }
574 { $description "Parses the Factor source code stored in a file. The initial vocabulary search path is used." }
575 { $errors "Throws an I/O error if there was an error reading from the file. Throws a parse error if the input is malformed." } ;
578 { $values { "file" "a pathname string" } }
579 { $description "Parses the Factor source code stored in a file and runs it. The initial vocabulary search path is used." }
580 { $errors "Throws an error if loading the file fails, there input is malformed, or if a runtime error occurs while calling the parsed quotation." } ;
583 { $values { "path" "a pathname string" } }
584 { $description "If the file exists, runs it with " { $link run-file } ", otherwise does nothing." } ;
587 { $values { "defspec" "a definition specifier" } }
588 { $description "Reloads the source file containing the definition." }
590 "Reloading a word definition:"
591 { $code "\\ foo reload" }
592 "A word's documentation:"
593 { $code "\\ foo >link reload" }
594 "A method definition:"
595 { $code "{ editor draw-gadget* } reload" }
597 { $code "\"handbook\" >link reload" }
601 { $values { "path" "a pathname string" } }
602 { $description "If bootstrapping, parses the source file and adds its top level form to the quotation being constructed with " { $link make } "; the bootstrap code uses this to build up a boot quotation to be run on image startup. If not bootstrapping, just runs the file normally." } ;
604 HELP: ?bootstrap-file
605 { $values { "path" "a pathname string" } }
606 { $description "If the file exists, loads it with " { $link bootstrap-file } ", otherwise does nothing." } ;
609 { $values { "str" string } { "output" string } }
610 { $description "Evaluates the Factor code in " { $snippet "str" } " with the " { $link stdio } " stream rebound to a string output stream, then outputs the resulting string." } ;