]> gitweb.factorcode.org Git - factor.git/blob - core/words/words.factor
definitions: Separate definition definitions.
[factor.git] / core / words / words.factor
1 ! Copyright (C) 2004, 2010 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays assocs definitions hashtables kernel
4 kernel.private math math.order namespaces quotations sequences
5 slots.private strings vocabs ;
6 FROM: assocs => change-at ;
7 IN: words
8
9 BUILTIN: word
10 { hashcode fixnum initial: 0 } name vocabulary
11 { def quotation initial: [ ] } props pic-def pic-tail-def
12 { sub-primitive read-only } ;
13
14 ! Need a dummy word here because BUILTIN: word is not a real word
15 ! and parse-datum looks for things that are actually words instead of
16 ! also looking for classes
17 : word ( -- * ) "dummy word" throw ;
18
19 SYMBOL: last-word-symbol
20
21 : last-word ( -- word ) \ last-word-symbol get-global ;
22
23 : set-last-word ( word -- ) \ last-word-symbol set-global ;
24
25 M: word execute (execute) ;
26
27 M: word ?execute execute( -- value ) ; inline
28
29 M: word <=>
30     [ [ name>> ] [ vocabulary>> ] bi 2array ] compare ;
31
32 M: word definer drop \ : \ ; ;
33
34 M: word definition def>> ;
35
36 : word-prop ( word name -- value ) swap props>> at ;
37
38 : remove-word-prop ( word name -- ) swap props>> delete-at ;
39
40 : set-word-prop ( word value name -- )
41     over
42     [ pick props>> ?set-at >>props drop ]
43     [ nip remove-word-prop ] if ;
44
45 : change-word-prop ( ..a word prop quot: ( ..a value -- ..b newvalue ) -- ..b )
46     [ swap props>> ] dip change-at ; inline
47
48 : reset-props ( word seq -- ) [ remove-word-prop ] with each ;
49
50 <PRIVATE
51
52 : caller ( callstack -- word ) callstack>array <reversed> third ;
53
54 PRIVATE>
55
56 TUPLE: undefined word ;
57 : undefined ( -- * ) callstack caller \ undefined boa throw ;
58
59 : undefined-def ( -- quot )
60     #! 'f' inhibits tail call optimization in non-optimizing
61     #! compiler, ensuring that we can pull out the caller word
62     #! above.
63     [ undefined f ] ;
64
65 PREDICATE: deferred < word def>> undefined-def = ;
66 M: deferred definer drop \ DEFER: f ;
67 M: deferred definition drop f ;
68
69 PREDICATE: primitive < word "primitive" word-prop ;
70 M: primitive definer drop \ PRIMITIVE: f ;
71 M: primitive definition drop f ;
72
73 : lookup-word ( name vocab -- word ) vocab-words at ;
74
75 : target-word ( word -- target )
76     [ name>> ] [ vocabulary>> ] bi lookup-word ;
77
78 SYMBOL: bootstrapping?
79
80 : if-bootstrapping ( true false -- )
81     [ bootstrapping? get ] 2dip if ; inline
82
83 : bootstrap-word ( word -- target )
84     [ target-word ] [ ] if-bootstrapping ;
85
86 GENERIC: crossref? ( word -- ? )
87
88 M: word crossref?
89     dup "forgotten" word-prop [ drop f ] [ vocabulary>> >boolean ] if ;
90
91 GENERIC: subwords ( word -- seq )
92
93 M: word subwords drop f ;
94
95 GENERIC: parent-word ( word -- word/f )
96
97 M: word parent-word drop f ;
98
99 : define ( word def -- )
100     over changed-definition [ ] like >>def drop ;
101
102 : changed-effect ( word -- )
103     [ changed-effects get add-to-unit ]
104     [ dup primitive? [ drop ] [ changed-definition ] if ] bi ;
105
106 : set-stack-effect ( effect word -- )
107     2dup "declared-effect" word-prop = [ 2drop ] [
108         [ nip changed-effect ]
109         [ nip subwords [ changed-effect ] each ]
110         [ swap "declared-effect" set-word-prop ]
111         2tri
112     ] if ;
113
114 : define-declared ( word def effect -- )
115     [ nip swap set-stack-effect ] [ drop define ] 3bi ;
116
117 : make-deprecated ( word -- )
118     t "deprecated" set-word-prop ;
119
120 : inline? ( obj -- ? )
121     dup word? [ "inline" word-prop ] [ drop f ] if ; inline
122
123 : recursive? ( obj -- ? )
124     dup word? [ "recursive" word-prop ] [ drop f ] if ; inline
125
126 : inline-recursive? ( obj -- ? )
127     dup word? [
128         dup "inline" word-prop
129         [ "recursive" word-prop ] [ drop f ] if
130     ] [ drop f ] if ; inline
131
132 ERROR: cannot-be-inline word ;
133
134 GENERIC: make-inline ( word -- )
135
136 M: word make-inline
137     dup inline? [ drop ] [
138         [ t "inline" set-word-prop ]
139         [ changed-effect ]
140         bi
141     ] if ;
142
143 : define-inline ( word def effect -- )
144     [ define-declared ] [ 2drop make-inline ] 3bi ;
145
146 : make-recursive ( word -- )
147     t "recursive" set-word-prop ;
148
149 GENERIC: flushable? ( word -- ? )
150
151 M: word flushable?
152     [ "flushable" word-prop ]
153     [ parent-word dup [ flushable? ] when ] bi or ;
154
155 : make-flushable ( word -- )
156     t "flushable" set-word-prop ;
157
158 GENERIC: foldable? ( word -- ? )
159
160 M: word foldable?
161     [ "foldable" word-prop ]
162     [ parent-word dup [ foldable? ] when ] bi or ;
163
164 : make-foldable ( word -- )
165     dup make-flushable t "foldable" set-word-prop ;
166
167 GENERIC: reset-word ( word -- )
168
169 M: word reset-word
170     dup flushable? [ dup changed-conditionally ] when
171     {
172         "unannotated-def" "parsing" "inline" "recursive"
173         "foldable" "flushable" "reading" "writing" "reader"
174         "writer" "delimiter" "deprecated"
175     } reset-props ;
176
177 : reset-generic ( word -- )
178     [ subwords forget-all ]
179     [ reset-word ]
180     [
181         f >>pic-def
182         f >>pic-tail-def
183         {
184             "methods"
185             "combination"
186             "default-method"
187             "engines"
188             "decision-tree"
189         } reset-props
190     ] tri ;
191
192 : <word> ( name vocab -- word )
193     2dup 0 hash-combine hash-combine >fixnum (word) dup new-word ;
194
195 : <uninterned-word> ( name -- word )
196     f \ <uninterned-word> counter >fixnum (word)
197     new-words get [ dup new-word ] when ;
198
199 : gensym ( -- word )
200     "( gensym )" <uninterned-word> ;
201
202 : define-temp ( quot effect -- word )
203     [ gensym dup ] 2dip define-declared ;
204
205 : reveal ( word -- )
206     dup [ name>> ] [ vocabulary>> ] bi dup vocab-words
207     [ ] [ no-vocab ] ?if
208     set-at ;
209
210 ERROR: bad-create name vocab ;
211
212 : check-create ( name vocab -- name vocab )
213     2dup [ string? ] [ [ string? ] [ vocab? ] bi or ] bi* and
214     [ bad-create ] unless ;
215
216 : create ( name vocab -- word )
217     check-create 2dup lookup-word
218     dup [ 2nip ] [
219         drop
220         vocab-name <word>
221         dup reveal
222         dup changed-definition
223     ] if ;
224
225 : constructor-word ( name vocab -- word )
226     [ "<" ">" surround ] dip create ;
227
228 PREDICATE: parsing-word < word "parsing" word-prop ;
229
230 M: parsing-word definer drop \ SYNTAX: \ ; ;
231
232 : define-syntax ( word quot -- )
233     [ drop ] [ define ] 2bi t "parsing" set-word-prop ;
234
235 : delimiter? ( obj -- ? )
236     dup word? [ "delimiter" word-prop ] [ drop f ] if ;
237
238 : deprecated? ( obj -- ? )
239     dup word? [ "deprecated" word-prop ] [ drop f ] if ;
240
241 ! Definition protocol
242 M: word where "loc" word-prop ;
243
244 M: word set-where swap "loc" set-word-prop ;
245
246 M: word forget*
247     dup "forgotten" word-prop [ drop ] [
248         [ subwords forget-all ]
249         [ [ name>> ] [ vocabulary>> vocab-words ] bi delete-at ]
250         [ t "forgotten" set-word-prop ]
251         tri
252     ] if ;
253
254 M: word hashcode*
255     nip 1 slot { fixnum } declare ; inline foldable
256
257 M: word literalize <wrapper> ;
258
259 INSTANCE: word definition-mixin