1 ! Copyright (C) 2005, 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays definitions generic assocs kernel math namespaces
4 sequences strings vectors words words.symbol quotations io combinators
5 sorting splitting math.parser effects continuations io.files vocabs
6 io.encodings.utf8 source-files classes hashtables compiler.errors
7 compiler.units accessors sets lexer vocabs.parser effects.parser slots ;
11 file get lexer get line>> 2dup and
12 [ [ path>> ] dip 2array ] [ 2drop f ] if ;
14 : save-location ( definition -- )
15 location remember-definition ;
19 t parser-notes set-global
21 : parser-notes? ( -- ? )
22 parser-notes get "quiet" get not and ;
26 file get [ path>> write ":" write ] when*
27 lexer get [ line>> number>string write ": " write ] when*
28 "Note:" print dup print
31 M: parsing-word stack-effect drop (( parsed -- parsed )) ;
33 TUPLE: no-current-vocab ;
35 : no-current-vocab ( -- vocab )
36 \ no-current-vocab boa
37 { { "Define words in scratchpad vocabulary" "scratchpad" } }
38 throw-restarts dup set-in ;
40 : current-vocab ( -- str )
41 in get [ no-current-vocab ] unless* ;
43 : create-in ( str -- word )
44 current-vocab create dup set-word dup save-location ;
46 : CREATE ( -- word ) scan create-in ;
48 : CREATE-WORD ( -- word ) CREATE dup reset-generic ;
54 : no-word-restarted ( restart-value -- word )
58 [ amended-use get dup [ push ] [ 2drop ] if ]
59 [ "Added \"" "\" vocabulary to search path" surround note. ]
63 : no-word ( name -- newword )
64 dup words-named [ forward-reference? not ] filter
65 dup length 1 = auto-use? get and
66 [ nip first no-word-restarted ]
67 [ <no-word-error> throw-restarts no-word-restarted ]
70 : check-forward ( str word -- word/f )
71 dup forward-reference? [
75 [ forward-reference? not ] find nip
80 : search ( str -- word/f )
81 dup use get assoc-stack check-forward ;
83 : scan-word ( -- word/number/f )
86 dup string>number [ ] [ no-word ] ?if
90 ERROR: staging-violation word ;
92 : execute-parsing ( accum word -- accum )
93 dup changed-definitions get key? [ staging-violation ] when
94 execute( accum -- accum ) ;
96 : scan-object ( -- object )
97 scan-word dup parsing-word?
98 [ V{ } clone swap execute-parsing first ] when ;
100 : parse-step ( accum end -- accum ? )
102 { [ 2dup eq? ] [ 2drop f ] }
103 { [ dup not ] [ drop unexpected-eof t ] }
104 { [ dup delimiter? ] [ unexpected t ] }
105 { [ dup parsing-word? ] [ nip execute-parsing t ] }
109 : (parse-until) ( accum end -- accum )
110 [ parse-step ] keep swap [ (parse-until) ] [ drop ] if ;
112 : parse-until ( end -- vec )
113 100 <vector> swap (parse-until) ;
115 SYMBOL: quotation-parser
117 HOOK: parse-quotation quotation-parser ( -- quot )
119 M: f parse-quotation \ ] parse-until >quotation ;
121 : parsed ( accum obj -- accum ) over push ;
123 : (parse-lines) ( lexer -- quot )
124 [ f parse-until >quotation ] with-lexer ;
126 : parse-lines ( lines -- quot )
127 lexer-factory get call( lines -- lexer ) (parse-lines) ;
129 : parse-literal ( accum end quot -- accum )
130 [ parse-until ] dip call parsed ; inline
132 : parse-definition ( -- quot )
133 \ ; parse-until >quotation ;
135 : (:) ( -- word def effect )
138 parse-definition swap ;
142 : parse-base ( parsed base -- parsed )
143 scan swap base> [ bad-number ] unless* parsed ;
145 SYMBOL: bootstrap-syntax
147 : with-file-vocabs ( quot -- )
149 f in set { "syntax" } set-use
150 bootstrap-syntax get [ use get push ] when*
152 ] with-scope ; inline
154 SYMBOL: interactive-vocabs
202 } interactive-vocabs set-global
204 : with-interactive-vocabs ( quot -- )
207 interactive-vocabs get set-use
209 ] with-scope ; inline
211 SYMBOL: print-use-hook
213 print-use-hook [ [ ] ] initialize
215 : parse-fresh ( lines -- quot )
217 V{ } clone amended-use set
219 amended-use get empty? [ print-use-hook get call( -- ) ] unless
222 : parsing-file ( file -- )
223 "quiet" get [ drop ] [ "Loading " write print flush ] if ;
225 : filter-moved ( assoc1 assoc2 -- seq )
226 swap assoc-diff keys [
228 { [ dup where dup [ first ] when file get path>> = not ] [ f ] }
229 { [ dup reader-method? ] [ f ] }
230 { [ dup writer-method? ] [ f ] }
235 : removed-definitions ( -- assoc1 assoc2 )
236 new-definitions old-definitions
237 [ get first2 assoc-union ] bi@ ;
239 : removed-classes ( -- assoc1 assoc2 )
240 new-definitions old-definitions
243 : forget-removed-definitions ( -- )
244 removed-definitions filter-moved forget-all ;
246 : reset-removed-classes ( -- )
248 filter-moved [ class? ] filter [ forget-class ] each ;
250 : fix-class-words ( -- )
251 #! If a class word had a compound definition which was
252 #! removed, it must go back to being a symbol.
253 new-definitions get first2
254 filter-moved [ [ reset-generic ] [ define-symbol ] bi ] each ;
256 : forget-smudged ( -- )
257 forget-removed-definitions
258 reset-removed-classes
261 : finish-parsing ( lines quot -- )
264 [ record-definitions ]
268 : parse-stream ( stream name -- quot )
271 lines dup parse-fresh
272 [ nip ] [ finish-parsing ] 2bi
275 ] with-compilation-unit ;
277 : parse-file-restarts ( file -- restarts )
278 "Load " " again" surround t 2array 1array ;
280 : parse-file ( file -- quot )
283 [ parsing-file ] keep
284 [ utf8 <file-reader> ] keep
286 ] with-compiler-errors
288 over parse-file-restarts rethrow-restarts
292 : run-file ( file -- )
293 parse-file call( -- ) ;
295 : ?run-file ( path -- )
296 dup exists? [ run-file ] [ drop ] if ;