]> gitweb.factorcode.org Git - factor.git/blob - core/vocabs/parser/parser.factor
Merge branch 'master' of git://factorcode.org/git/factor
[factor.git] / core / vocabs / parser / parser.factor
1 ! Copyright (C) 2007, 2009 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
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 { extra-words vector }
30 { auto-used vector } ;
31
32 : <manifest> ( -- manifest )
33     manifest new
34         H{ } clone >>search-vocab-names
35         V{ } clone >>search-vocabs
36         V{ } clone >>qualified-vocabs
37         V{ } clone >>extra-words
38         V{ } clone >>auto-used ;
39
40 M: manifest clone
41     call-next-method
42         [ clone ] change-search-vocab-names
43         [ clone ] change-search-vocabs
44         [ clone ] change-qualified-vocabs
45         [ clone ] change-extra-words
46         [ clone ] change-auto-used ;
47
48 TUPLE: extra-words words ;
49
50 M: extra-words equal?
51     over extra-words? [ [ words>> ] bi@ eq? ] [ 2drop f ] if ;
52
53 C: <extra-words> extra-words
54
55 <PRIVATE
56
57 : clear-manifest ( -- )
58     manifest get
59     [ search-vocab-names>> clear-assoc ]
60     [ search-vocabs>> delete-all ]
61     [ qualified-vocabs>> delete-all ]
62     tri ;
63
64 : (add-qualified) ( qualified -- )
65     manifest get qualified-vocabs>> push ;
66
67 : (from) ( vocab words -- vocab words words' assoc )
68     2dup swap load-vocab words>> ;
69
70 : extract-words ( seq assoc -- assoc' )
71     extract-keys dup [ [ drop ] [ no-word-error ] if ] assoc-each ;
72
73 : (lookup) ( name assoc -- word/f )
74     at dup forward-reference? [ drop f ] when ;
75
76 : (use-words) ( assoc -- extra-words seq )
77     <extra-words> manifest get qualified-vocabs>> ;
78
79 PRIVATE>
80
81 : set-current-vocab ( name -- )
82     create-vocab
83     [ manifest get (>>current-vocab) ]
84     [ words>> <extra-words> (add-qualified) ] bi ;
85
86 TUPLE: no-current-vocab ;
87
88 : no-current-vocab ( -- vocab )
89     \ no-current-vocab boa
90     { { "Define words in scratchpad vocabulary" "scratchpad" } }
91     throw-restarts dup set-current-vocab ;
92
93 : current-vocab ( -- vocab )
94     manifest get current-vocab>> [ no-current-vocab ] unless* ;
95
96 : begin-private ( -- )
97     manifest get current-vocab>> vocab-name ".private" ?tail
98     [ drop ] [ ".private" append set-current-vocab ] if ;
99
100 : end-private ( -- )
101     manifest get current-vocab>> vocab-name ".private" ?tail
102     [ set-current-vocab ] [ drop ] if ;
103
104 : using-vocab? ( vocab -- ? )
105     vocab-name manifest get search-vocab-names>> key? ;
106
107 : use-vocab ( vocab -- )
108     dup using-vocab?
109     [ vocab-name "Already using ``" "'' vocabulary" surround note. ] [
110         manifest get
111         [ [ load-vocab ] dip search-vocabs>> push ]
112         [ [ vocab-name ] dip search-vocab-names>> conjoin ]
113         2bi
114     ] if ;
115
116 : auto-use-vocab ( vocab -- )
117     [ use-vocab ] [ manifest get auto-used>> push ] bi ;
118
119 : auto-used? ( -- ? ) manifest get auto-used>> length 0 > ;
120
121 : unuse-vocab ( vocab -- )
122     dup using-vocab? [
123         manifest get
124         [ [ load-vocab ] dip search-vocabs>> delq ]
125         [ [ vocab-name ] dip search-vocab-names>> delete-at ]
126         2bi
127     ] [ drop ] if ;
128
129 : only-use-vocabs ( vocabs -- )
130     clear-manifest [ vocab ] filter [ use-vocab ] each ;
131
132 TUPLE: qualified vocab prefix words ;
133
134 : <qualified> ( vocab prefix -- qualified )
135     2dup
136     [ load-vocab words>> ] [ CHAR: : suffix ] bi*
137     [ swap [ prepend ] dip ] curry assoc-map
138     qualified boa ;
139
140 : add-qualified ( vocab prefix -- )
141     <qualified> (add-qualified) ;
142
143 TUPLE: from vocab names words ;
144
145 : <from> ( vocab words -- from )
146     (from) extract-words from boa ;
147
148 : add-words-from ( vocab words -- )
149     <from> (add-qualified) ;
150
151 TUPLE: exclude vocab names words ;
152
153 : <exclude> ( vocab words -- from )
154     (from) [ nip ] [ extract-words ] 2bi assoc-diff exclude boa ;
155
156 : add-words-excluding ( vocab words -- )
157     <exclude> (add-qualified) ;
158
159 TUPLE: rename word vocab words ;
160
161 : <rename> ( word vocab new-name -- rename )
162     [ 2dup load-vocab words>> dupd at [ ] [ no-word-error ] ?if ] dip
163     associate rename boa ;
164
165 : add-renamed-word ( word vocab new-name -- )
166     <rename> (add-qualified) ;
167
168 : use-words ( assoc -- ) (use-words) push ;
169
170 : unuse-words ( assoc -- ) (use-words) delete ;
171
172 TUPLE: ambiguous-use-error words ;
173
174 : <ambiguous-use-error> ( words -- error restarts )
175     [ \ ambiguous-use-error boa ] [ word-restarts ] bi ;
176
177 <PRIVATE
178
179 : (vocab-search) ( name assocs -- words n )
180     [ words>> (lookup) ] with map
181     sift dup length ;
182
183 : vocab-search ( name manifest -- word/f )
184     search-vocabs>>
185     (vocab-search) {
186         { 0 [ drop f ] }
187         { 1 [ first ] }
188         [
189             drop <ambiguous-use-error> throw-restarts
190             dup [ vocabulary>> ] [ name>> 1array ] bi add-words-from
191         ]
192     } case ;
193
194 : qualified-search ( name manifest -- word/f )
195     qualified-vocabs>>
196     (vocab-search) 0 = [ drop f ] [ last ] if ;
197
198 PRIVATE>
199
200 : search-manifest ( name manifest -- word/f )
201     2dup qualified-search dup [ 2nip ] [ drop vocab-search ] if ;
202
203 : search ( name -- word/f )
204     manifest get search-manifest ;