1 ! Copyright (C) 2004, 2010 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays definitions kernel kernel.private
4 slots.private math namespaces sequences strings vectors sbufs
5 quotations assocs hashtables sorting vocabs math.order sets
7 FROM: assocs => change-at ;
10 : word ( -- word ) \ word get-global ;
12 : set-word ( word -- ) \ word set-global ;
14 M: word execute (execute) ;
16 M: word ?execute execute( -- value ) ; inline
19 [ [ name>> ] [ vocabulary>> ] bi 2array ] compare ;
21 M: word definer drop \ : \ ; ;
23 M: word definition def>> ;
25 : word-prop ( word name -- value ) swap props>> at ;
27 : remove-word-prop ( word name -- ) swap props>> delete-at ;
29 : set-word-prop ( word value name -- )
31 [ pick props>> ?set-at >>props drop ]
32 [ nip remove-word-prop ] if ;
34 : change-word-prop ( ..a word prop quot: ( ..a value -- ..b newvalue ) -- ..b )
35 [ swap props>> ] dip change-at ; inline
37 : reset-props ( word seq -- ) [ remove-word-prop ] with each ;
41 : caller ( callstack -- word ) callstack>array <reversed> third ;
45 TUPLE: undefined word ;
46 : undefined ( -- * ) callstack caller \ undefined boa throw ;
48 : undefined-def ( -- quot )
49 #! 'f' inhibits tail call optimization in non-optimizing
50 #! compiler, ensuring that we can pull out the caller word
54 PREDICATE: deferred < word def>> undefined-def = ;
55 M: deferred definer drop \ DEFER: f ;
56 M: deferred definition drop f ;
58 PREDICATE: primitive < word "primitive" word-prop ;
59 M: primitive definer drop \ PRIMITIVE: f ;
60 M: primitive definition drop f ;
62 : lookup-word ( name vocab -- word ) vocab-words at ;
64 : target-word ( word -- target )
65 [ name>> ] [ vocabulary>> ] bi lookup-word ;
67 SYMBOL: bootstrapping?
69 : if-bootstrapping ( true false -- )
70 [ bootstrapping? get ] 2dip if ; inline
72 : bootstrap-word ( word -- target )
73 [ target-word ] [ ] if-bootstrapping ;
75 GENERIC: crossref? ( word -- ? )
78 dup "forgotten" word-prop [ drop f ] [ vocabulary>> >boolean ] if ;
80 GENERIC: subwords ( word -- seq )
82 M: word subwords drop f ;
84 GENERIC: parent-word ( word -- word/f )
86 M: word parent-word drop f ;
88 : define ( word def -- )
89 over changed-definition [ ] like >>def drop ;
91 : changed-effect ( word -- )
92 [ dup changed-effects get set-in-unit ]
93 [ dup primitive? [ drop ] [ changed-definition ] if ] bi ;
95 : set-stack-effect ( effect word -- )
96 2dup "declared-effect" word-prop = [ 2drop ] [
97 [ nip changed-effect ]
98 [ nip subwords [ changed-effect ] each ]
99 [ swap "declared-effect" set-word-prop ]
103 : define-declared ( word def effect -- )
104 [ nip swap set-stack-effect ] [ drop define ] 3bi ;
106 : make-deprecated ( word -- )
107 t "deprecated" set-word-prop ;
109 : inline? ( word -- ? ) "inline" word-prop ; inline
111 : inline-recursive? ( word -- ? )
112 dup "inline" word-prop
113 [ "recursive" word-prop ] [ drop f ] if ; inline
115 ERROR: cannot-be-inline word ;
117 GENERIC: make-inline ( word -- )
120 dup inline? [ drop ] [
121 [ t "inline" set-word-prop ]
126 : define-inline ( word def effect -- )
127 [ define-declared ] [ 2drop make-inline ] 3bi ;
129 : make-recursive ( word -- )
130 t "recursive" set-word-prop ;
132 GENERIC: flushable? ( word -- ? )
135 [ "flushable" word-prop ]
136 [ parent-word dup [ flushable? ] when ] bi or ;
138 : make-flushable ( word -- )
139 t "flushable" set-word-prop ;
141 GENERIC: foldable? ( word -- ? )
144 [ "foldable" word-prop ]
145 [ parent-word dup [ foldable? ] when ] bi or ;
147 : make-foldable ( word -- )
148 dup make-flushable t "foldable" set-word-prop ;
150 GENERIC: reset-word ( word -- )
153 dup flushable? [ dup changed-conditionally ] when
155 "unannotated-def" "parsing" "inline" "recursive"
156 "foldable" "flushable" "reading" "writing" "reader"
157 "writer" "delimiter" "deprecated"
160 : reset-generic ( word -- )
161 [ subwords forget-all ]
175 : <word> ( name vocab -- word )
176 2dup 0 hash-combine hash-combine >fixnum (word) dup new-word ;
178 : <uninterned-word> ( name -- word )
179 f \ <uninterned-word> counter >fixnum (word)
180 new-words get [ dup new-word ] when ;
183 "( gensym )" <uninterned-word> ;
185 : define-temp ( quot effect -- word )
186 [ gensym dup ] 2dip define-declared ;
189 dup [ name>> ] [ vocabulary>> ] bi dup vocab-words
193 ERROR: bad-create name vocab ;
195 : check-create ( name vocab -- name vocab )
196 2dup [ string? ] [ [ string? ] [ vocab? ] bi or ] bi* and
197 [ bad-create ] unless ;
199 : create ( name vocab -- word )
200 check-create 2dup lookup-word
205 dup changed-definition
208 : constructor-word ( name vocab -- word )
209 [ "<" ">" surround ] dip create ;
211 PREDICATE: parsing-word < word "parsing" word-prop ;
213 M: parsing-word definer drop \ SYNTAX: \ ; ;
215 : define-syntax ( word quot -- )
216 [ drop ] [ define ] 2bi t "parsing" set-word-prop ;
218 : delimiter? ( obj -- ? )
219 dup word? [ "delimiter" word-prop ] [ drop f ] if ;
221 : deprecated? ( obj -- ? )
222 dup word? [ "deprecated" word-prop ] [ drop f ] if ;
224 ! Definition protocol
225 M: word where "loc" word-prop ;
227 M: word set-where swap "loc" set-word-prop ;
230 dup "forgotten" word-prop [ drop ] [
231 [ subwords forget-all ]
232 [ [ name>> ] [ vocabulary>> vocab-words ] bi delete-at ]
233 [ t "forgotten" set-word-prop ]
238 nip 1 slot { fixnum } declare ; inline foldable
240 M: word literalize <wrapper> ;
242 INSTANCE: word definition