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 ;
9 { hashcode fixnum initial: 0 } name vocabulary
10 { def quotation initial: [ ] } props pic-def pic-tail-def
11 { sub-primitive read-only } ;
13 PRIMITIVE: word-code ( word -- start end )
14 PRIMITIVE: word-optimized? ( word -- ? )
17 PRIMITIVE: (word) ( name vocab hashcode -- word )
20 : last-word ( -- word ) \ last-word get-global ;
22 : set-last-word ( word -- ) \ last-word set-global ;
24 M: word execute (execute) ;
27 [ [ name>> ] [ vocabulary>> ] bi 2array ] compare ;
29 M: word definer drop \ : \ ; ;
31 M: word definition def>> ;
33 : word-prop ( word name -- value ) swap props>> at ;
35 : remove-word-prop ( word name -- ) swap props>> delete-at ;
37 : remove-word-props ( word seq -- )
38 swap props>> [ delete-at ] curry each ;
40 : set-word-prop ( word value name -- )
42 [ pick props>> ?set-at >>props drop ]
43 [ nip remove-word-prop ] if ;
45 : change-word-prop ( ..a word prop quot: ( ..a value -- ..b newvalue ) -- ..b )
46 [ swap props>> ] dip change-at ; inline
50 : caller ( callstack -- word )
51 callstack>array first ;
55 TUPLE: undefined-word word ;
57 : undefined ( -- * ) get-callstack caller undefined-word boa throw ;
59 : undefined-def ( -- quot )
60 ! 'f' inhibits tail call optimization in non-optimizing
61 ! compiler, ensuring that we can pull out the caller word
65 PREDICATE: deferred < word def>> undefined-def = ;
66 M: deferred definer drop \ DEFER: f ;
67 M: deferred definition drop f ;
69 PREDICATE: primitive < word "primitive" word-prop ;
70 M: primitive definer drop \ PRIMITIVE: f ;
71 M: primitive definition drop f ;
73 ERROR: invalid-primitive vocabulary word effect ;
74 : ensure-primitive ( vocabulary word effect -- )
76 [ drop vocabulary>> = ]
77 [ drop nip primitive? ]
78 [ [ nip "declared-effect" word-prop ] dip = ] 3tri and and
79 [ 3drop ] [ invalid-primitive ] if ;
81 : lookup-word ( name vocab -- word ) vocab-words-assoc at ;
83 : target-word ( word -- target )
84 [ name>> ] [ vocabulary>> ] bi lookup-word ;
86 SYMBOL: bootstrapping?
88 : if-bootstrapping ( true false -- )
89 [ bootstrapping? get ] 2dip if ; inline
91 : bootstrap-word ( word -- target )
92 [ target-word ] [ ] if-bootstrapping ;
94 GENERIC: crossref? ( word -- ? )
97 dup "forgotten" word-prop [ drop f ] [ vocabulary>> >boolean ] if ;
99 GENERIC: subwords ( word -- seq )
101 M: word subwords drop f ;
103 GENERIC: parent-word ( word -- word/f )
105 M: word parent-word drop f ;
107 : define ( word def -- )
108 over changed-definition [ ] like >>def drop ;
110 : changed-effect ( word -- )
111 [ changed-effects get add-to-unit ]
112 [ dup primitive? [ drop ] [ changed-definition ] if ] bi ;
114 : set-stack-effect ( word effect -- )
115 2dup [ "declared-effect" word-prop ] dip =
117 [ drop changed-effect ]
118 [ drop subwords [ changed-effect ] each ]
119 [ "declared-effect" set-word-prop ]
123 : define-declared ( word def effect -- )
124 [ nip set-stack-effect ] [ drop define ] 3bi ;
126 : make-deprecated ( word -- )
127 t "deprecated" set-word-prop ;
129 : word-prop? ( obj string -- ? )
130 over word? [ word-prop ] [ 2drop f ] if ; inline
132 : word-props? ( obj seq -- ? )
133 over word? [ [ word-prop ] with all? ] [ 2drop f ] if ; inline
135 : inline? ( obj -- ? ) "inline" word-prop? ; inline
137 : recursive? ( obj -- ? ) "recursive" word-prop? ; inline
139 : inline-recursive? ( obj -- ? )
140 { "inline" "recursive" } word-props? ; inline
142 ERROR: cannot-be-inline word ;
144 GENERIC: make-inline ( word -- )
147 dup inline? [ drop ] [
148 [ t "inline" set-word-prop ]
153 : define-inline ( word def effect -- )
154 [ define-declared ] [ 2drop make-inline ] 3bi ;
156 : make-recursive ( word -- )
157 t "recursive" set-word-prop ;
159 GENERIC: flushable? ( word -- ? )
162 [ "flushable" word-prop ]
163 [ parent-word dup [ flushable? ] when ] bi or ;
165 : make-flushable ( word -- )
166 t "flushable" set-word-prop ;
168 GENERIC: foldable? ( word -- ? )
171 [ "foldable" word-prop ]
172 [ parent-word dup [ foldable? ] when ] bi or ;
174 : make-foldable ( word -- )
176 [ t "foldable" set-word-prop ] bi ;
178 GENERIC: reset-word ( word -- )
181 dup flushable? [ dup changed-conditionally ] when
183 "unannotated-def" "parsing" "inline" "recursive"
184 "foldable" "flushable" "reading" "writing" "reader"
185 "writer" "delimiter" "deprecated"
186 } remove-word-props ;
188 : reset-generic ( word -- )
189 [ subwords forget-all ]
203 : <word> ( name vocab -- word )
204 over hashcode over hashcode hash-combine >fixnum (word) dup new-word ;
206 : <uninterned-word> ( name -- word )
207 f \ <uninterned-word> counter >fixnum (word)
208 new-words get [ dup new-word ] when ;
211 "( gensym )" <uninterned-word> ;
213 : define-temp ( quot effect -- word )
214 [ gensym dup ] 2dip define-declared ;
217 dup [ name>> ] [ vocabulary>> ] bi dup vocab-words-assoc
218 [ ] [ no-vocab ] ?if set-at ;
220 ERROR: bad-create name vocab ;
222 : check-create ( name vocab -- name vocab )
223 2dup [ string? ] [ [ string? ] [ vocab? ] bi or ] bi* and
224 [ bad-create ] unless ;
226 : create-word ( name vocab -- word )
227 check-create 2dup lookup-word
231 dup changed-definition
234 : constructor-word ( name vocab -- word )
235 [ "<" ">" surround ] dip create-word ;
237 PREDICATE: parsing-word < word "parsing" word-prop ;
239 M: parsing-word definer drop \ SYNTAX: \ ; ;
241 : define-syntax ( word quot -- )
242 [ drop ] [ define ] 2bi t "parsing" set-word-prop ;
244 : delimiter? ( obj -- ? ) "delimiter" word-prop? ;
246 : deprecated? ( obj -- ? ) "deprecated" word-prop? ;
248 ! Definition protocol
249 M: word where "loc" word-prop ;
251 M: word set-where swap "loc" set-word-prop ;
254 dup "forgotten" word-prop [ drop ] [
255 [ subwords forget-all ]
256 [ [ name>> ] [ vocabulary>> vocab-words-assoc ] bi delete-at ]
257 [ t "forgotten" set-word-prop ]
261 ! Can be foldable because the hashcode itself is immutable
263 nip 1 slot { fixnum } declare ; inline foldable
265 M: word literalize <wrapper> ;
267 INSTANCE: word definition-mixin