1 ! Copyright (C) 2007, 2009 Eduardo Cavazos, Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors assocs definitions kernel namespaces sequences
4 sorting splitting strings ;
9 TUPLE: vocab < identity-tuple
12 source-loaded? docs-loaded? ;
14 ! sources-loaded? slot is one of these three
19 : <vocab> ( name -- vocab )
24 ERROR: bad-vocab-name name ;
26 : check-vocab-name ( name -- name )
27 dup string? [ bad-vocab-name ] unless
28 dup [ ":/\\ " member? ] any? [ bad-vocab-name ] when ;
30 TUPLE: vocab-link name ;
32 C: <vocab-link> vocab-link
34 UNION: vocab-spec vocab vocab-link ;
36 GENERIC: vocab-name ( vocab-spec -- name )
38 M: vocab vocab-name name>> ;
40 M: vocab-link vocab-name name>> ;
42 M: object vocab-name check-vocab-name ;
44 : vocab-name* ( vocab-spec -- name )
45 vocab-name ".private" ?tail drop ;
47 : private-vocab? ( vocab -- ? )
48 vocab-name ".private" tail? ;
50 GENERIC: lookup-vocab ( vocab-spec -- vocab )
52 M: vocab lookup-vocab ;
54 M: object lookup-vocab ( name -- vocab ) vocab-name dictionary get at ;
56 GENERIC: vocab-words ( vocab-spec -- words )
58 M: vocab vocab-words words>> ;
60 M: object vocab-words lookup-vocab vocab-words ;
64 GENERIC: vocab-help ( vocab-spec -- help )
66 M: vocab vocab-help help>> ;
68 M: object vocab-help lookup-vocab vocab-help ;
72 GENERIC: vocab-main ( vocab-spec -- main )
74 M: vocab vocab-main main>> ;
76 M: object vocab-main lookup-vocab vocab-main ;
80 SYMBOL: vocab-observers
82 GENERIC: vocab-changed ( vocab obj -- )
84 : add-vocab-observer ( obj -- )
85 vocab-observers get push ;
87 : remove-vocab-observer ( obj -- )
88 vocab-observers get remove-eq! drop ;
90 : notify-vocab-observers ( vocab -- )
91 vocab-observers get [ vocab-changed ] with each ;
93 : create-vocab ( name -- vocab )
94 check-vocab-name dictionary get
95 [ <vocab> dup notify-vocab-observers ] cache ;
97 ERROR: no-vocab name ;
100 dictionary get keys natural-sort ;
102 : words ( vocab -- seq )
105 : all-words ( -- seq )
106 dictionary get values [ words ] map concat ;
108 : words-named ( str -- seq )
109 dictionary get values
110 [ vocab-words at ] with map
113 : child-vocab? ( prefix name -- ? )
114 2dup = pick empty? or
115 [ 2drop t ] [ swap CHAR: . suffix head? ] if ;
117 : child-vocabs ( vocab -- seq )
118 vocab-name vocabs [ child-vocab? ] with filter ;
120 GENERIC: >vocab-link ( name -- vocab )
122 M: vocab-spec >vocab-link ;
124 M: object >vocab-link dup lookup-vocab [ ] [ <vocab-link> ] ?if ;
126 : forget-vocab ( vocab -- )
128 [ vocab-name dictionary get delete-at ]
129 [ notify-vocab-observers ] tri ;
131 M: vocab-spec forget* forget-vocab ;
135 PREDICATE: runnable-vocab < vocab
136 vocab-main >boolean ;
138 INSTANCE: vocab-spec definition-mixin
140 : call-require-hook ( name -- )
141 require-hook get call( name -- ) ;
143 GENERIC: require ( object -- )
145 M: vocab require name>> require ;
146 M: vocab-link require name>> require ;
148 ! When calling "foo.private" require, load "foo" instead, but only when
149 ! "foo.private" does not exist. The reason for this is that stage1 bootstrap
150 ! starts out with some .private vocabs that contain primitives, and
151 ! loading the public vocabs would cause circularity issues.
152 M: string require ( vocab -- )
153 dup ".private" ?tail [
156 [ nip call-require-hook ]
159 nip call-require-hook
162 : load-vocab ( name -- vocab )
163 [ require ] [ lookup-vocab ] bi ;