]> gitweb.factorcode.org Git - factor.git/blob - core/vocabs/parser/parser.factor
Language change: tuple slot setter words with stack effect ( value object -- ) are...
[factor.git] / core / vocabs / parser / parser.factor
1 ! Copyright (C) 2007, 2010 Daniel Ehrenberg, Bruno Deferrari,
2 ! Slava Pestov.
3 ! See http://factorcode.org/license.txt for BSD license.
4 USING: assocs hashtables kernel namespaces sequences
5 sets strings vocabs sorting accessors arrays compiler.units
6 combinators vectors splitting continuations math words
7 parser.notes ;
8 IN: vocabs.parser
9
10 ERROR: no-word-error name ;
11
12 : word-restarts ( possibilities -- restarts )
13     natural-sort
14     [ [ vocabulary>> "Use the " " vocabulary" surround ] keep ] { } map>assoc ;
15
16 : word-restarts-with-defer ( name possibilities -- restarts )
17     word-restarts
18     swap "Defer word in current vocabulary" swap 2array
19     suffix ;
20
21 : <no-word-error> ( name possibilities -- error restarts )
22     [ drop \ no-word-error boa ] [ word-restarts-with-defer ] 2bi ;
23
24 TUPLE: manifest
25 current-vocab
26 { search-vocab-names hashtable }
27 { search-vocabs vector }
28 { qualified-vocabs vector }
29 { auto-used vector } ;
30
31 : <manifest> ( -- manifest )
32     manifest new
33         H{ } clone >>search-vocab-names
34         V{ } clone >>search-vocabs
35         V{ } clone >>qualified-vocabs
36         V{ } clone >>auto-used ;
37
38 M: manifest clone
39     call-next-method
40         [ clone ] change-search-vocab-names
41         [ clone ] change-search-vocabs
42         [ clone ] change-qualified-vocabs
43         [ clone ] change-auto-used ;
44
45 TUPLE: extra-words words ;
46
47 M: extra-words equal?
48     over extra-words? [ [ words>> ] bi@ eq? ] [ 2drop f ] if ;
49
50 C: <extra-words> extra-words
51
52 : clear-manifest ( -- )
53     manifest get
54     [ search-vocab-names>> clear-assoc ]
55     [ search-vocabs>> delete-all ]
56     [ qualified-vocabs>> delete-all ]
57     tri ;
58
59 ERROR: no-word-in-vocab word vocab ;
60
61 <PRIVATE
62
63 : (add-qualified) ( qualified -- )
64     manifest get qualified-vocabs>> push ;
65
66 : (from) ( vocab words -- vocab words words' vocab )
67     2dup swap load-vocab ;
68
69 : extract-words ( seq vocab -- assoc )
70     [ words>> extract-keys dup ] [ name>> ] bi
71     [ swap [ 2drop ] [ no-word-in-vocab ] if ] curry assoc-each ;
72
73 : excluding-words ( seq vocab -- assoc )
74     [ nip words>> ] [ extract-words ] 2bi assoc-diff ;
75
76 : qualified-words ( prefix vocab -- assoc )
77     words>> swap [ swap [ swap ":" glue ] dip ] curry assoc-map ;
78
79 : (lookup) ( name assoc -- word/f )
80     at dup forward-reference? [ drop f ] when ;
81
82 : (use-words) ( assoc -- extra-words seq )
83     <extra-words> manifest get qualified-vocabs>> ;
84
85 PRIVATE>
86
87 : set-current-vocab ( name -- )
88     create-vocab
89     [ manifest get current-vocab<< ] [ (add-qualified) ] bi ;
90
91 : with-current-vocab ( name quot -- )
92     manifest get clone manifest [
93         [ set-current-vocab ] dip call
94     ] with-variable ; inline
95
96 TUPLE: no-current-vocab ;
97
98 : no-current-vocab ( -- vocab )
99     \ no-current-vocab boa
100     { { "Define words in scratchpad vocabulary" "scratchpad" } }
101     throw-restarts dup set-current-vocab ;
102
103 : current-vocab ( -- vocab )
104     manifest get current-vocab>> [ no-current-vocab ] unless* ;
105
106 : begin-private ( -- )
107     current-vocab name>> ".private" ?tail
108     [ drop ] [ ".private" append set-current-vocab ] if ;
109
110 : end-private ( -- )
111     current-vocab name>> ".private" ?tail
112     [ set-current-vocab ] [ drop ] if ;
113
114 : using-vocab? ( vocab -- ? )
115     vocab-name manifest get search-vocab-names>> key? ;
116
117 : use-vocab ( vocab -- )
118     dup using-vocab?
119     [ vocab-name "Already using ``" "'' vocabulary" surround note. ] [
120         manifest get
121         [ [ load-vocab ] dip search-vocabs>> push ]
122         [ [ vocab-name ] dip search-vocab-names>> conjoin ]
123         2bi
124     ] if ;
125
126 : auto-use-vocab ( vocab -- )
127     [ use-vocab ] [ manifest get auto-used>> push ] bi ;
128
129 : auto-used? ( -- ? ) manifest get auto-used>> length 0 > ;
130
131 : unuse-vocab ( vocab -- )
132     dup using-vocab? [
133         manifest get
134         [ [ load-vocab ] dip search-vocabs>> remove-eq! drop ]
135         [ [ vocab-name ] dip search-vocab-names>> delete-at ]
136         2bi
137     ] [ drop ] if ;
138
139 TUPLE: qualified vocab prefix words ;
140
141 : <qualified> ( vocab prefix -- qualified )
142     (from) qualified-words qualified boa ;
143
144 : add-qualified ( vocab prefix -- )
145     <qualified> (add-qualified) ;
146
147 TUPLE: from vocab names words ;
148
149 : <from> ( vocab words -- from )
150     (from) extract-words from boa ;
151
152 : add-words-from ( vocab words -- )
153     <from> (add-qualified) ;
154
155 TUPLE: exclude vocab names words ;
156
157 : <exclude> ( vocab words -- from )
158     (from) excluding-words exclude boa ;
159
160 : add-words-excluding ( vocab words -- )
161     <exclude> (add-qualified) ;
162
163 TUPLE: rename word vocab words ;
164
165 : <rename> ( word vocab new-name -- rename )
166     [ 2dup load-vocab words>> dupd at [ ] [ swap no-word-in-vocab ] ?if ] dip
167     associate rename boa ;
168
169 : add-renamed-word ( word vocab new-name -- )
170     <rename> (add-qualified) ;
171
172 : use-words ( assoc -- ) (use-words) push ;
173
174 : unuse-words ( assoc -- ) (use-words) remove! drop ;
175
176 TUPLE: ambiguous-use-error words ;
177
178 : <ambiguous-use-error> ( words -- error restarts )
179     [ \ ambiguous-use-error boa ] [ word-restarts ] bi ;
180
181 <PRIVATE
182
183 : (vocab-search) ( name assocs -- words n )
184     [ words>> (lookup) ] with map
185     sift dup length ;
186
187 : vocab-search ( name manifest -- word/f )
188     search-vocabs>>
189     (vocab-search) {
190         { 0 [ drop f ] }
191         { 1 [ first ] }
192         [
193             drop <ambiguous-use-error> throw-restarts
194             dup [ vocabulary>> ] [ name>> 1array ] bi add-words-from
195         ]
196     } case ;
197
198 : qualified-search ( name manifest -- word/f )
199     qualified-vocabs>>
200     (vocab-search) 0 = [ drop f ] [ last ] if ;
201
202 PRIVATE>
203
204 : search-manifest ( name manifest -- word/f )
205     2dup qualified-search dup [ 2nip ] [ drop vocab-search ] if ;
206
207 : search ( name -- word/f )
208     manifest get search-manifest ;
209
210 <PRIVATE
211
212 GENERIC: update ( search-path-elt -- valid? )
213
214 : trim-forgotten ( qualified-vocab -- valid? )
215     [ [ nip "forgotten" word-prop not ] assoc-filter ] change-words
216     words>> assoc-empty? not ;
217
218 M: from update trim-forgotten ;
219 M: rename update trim-forgotten ;
220 M: extra-words update trim-forgotten ;
221 M: exclude update trim-forgotten ;
222
223 M: qualified update
224     dup vocab>> vocab [
225         dup [ prefix>> ] [ vocab>> load-vocab ] bi qualified-words
226         >>words
227     ] [ drop f ] if ;
228
229 M: vocab update dup name>> vocab eq? ;
230
231 : update-manifest ( manifest -- )
232     [ dup [ name>> vocab ] when ] change-current-vocab
233     [ [ drop vocab ] assoc-filter ] change-search-vocab-names
234     dup search-vocab-names>> keys [ vocab ] V{ } map-as >>search-vocabs
235     qualified-vocabs>> [ update ] filter! drop ;
236
237 M: manifest definitions-changed ( assoc manifest -- )
238     nip update-manifest ;
239
240 PRIVATE>
241
242 : with-manifest ( quot -- )
243     <manifest> manifest [
244         [ call ] [
245             [ manifest get add-definition-observer call ]
246             [ manifest get remove-definition-observer ]
247             [ ]
248             cleanup
249         ] if-bootstrapping
250     ] with-variable ; inline