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