]> gitweb.factorcode.org Git - factor.git/blob - core/vocabs/loader/loader.factor
Merge branch 'master' of git://factorcode.org/git/factor
[factor.git] / core / vocabs / loader / loader.factor
1 ! Copyright (C) 2007, 2010 Eduardo Cavazos, Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: namespaces make sequences io io.files io.pathnames kernel
4 assocs words vocabs definitions parser continuations hashtables
5 sorting source-files arrays combinators strings system
6 math.parser splitting init accessors sets ;
7 IN: vocabs.loader
8
9 SYMBOL: vocab-roots
10
11 SYMBOL: add-vocab-root-hook
12
13 [
14     V{
15         "resource:core"
16         "resource:basis"
17         "resource:extra"
18         "resource:work"
19     } clone vocab-roots set-global
20
21     [ drop ] add-vocab-root-hook set-global
22 ] "vocabs.loader" add-startup-hook
23
24 : add-vocab-root ( root -- )
25     [ vocab-roots get adjoin ]
26     [ add-vocab-root-hook get-global call( root -- ) ] bi ;
27
28 SYMBOL: root-cache
29
30 root-cache [ H{ } clone ] initialize
31
32 ERROR: not-found-in-roots path ;
33
34 <PRIVATE
35
36 : find-root-for ( path -- path/f )
37     vocab-roots get [ prepend-path exists? ] with find nip ;
38
39 M: string vocab-path ( string -- path/f )
40     dup find-root-for [ prepend-path ] [ not-found-in-roots ] if* ;
41
42 PRIVATE>
43
44 : vocab-dir ( vocab -- dir )
45     vocab-name { { CHAR: . CHAR: / } } substitute ;
46
47 : vocab-dir+ ( vocab str/f -- path )
48     [ vocab-name "." split ] dip
49     [ [ dup last ] dip append suffix ] when*
50     "/" join ;
51
52 : find-vocab-root ( vocab -- path/f )
53     vocab-name dup root-cache get at
54     [ ] [ ".factor" vocab-dir+ find-root-for ] ?if ;
55
56 : vocab-append-path ( vocab path -- newpath )
57     swap find-vocab-root dup [ prepend-path ] [ 2drop f ] if ;
58
59 : vocab-source-path ( vocab -- path/f )
60     dup ".factor" vocab-dir+ vocab-append-path ;
61
62 : vocab-docs-path ( vocab -- path/f )
63     dup "-docs.factor" vocab-dir+ vocab-append-path ;
64
65 SYMBOL: load-help?
66
67 ! Defined by vocabs.metadata
68 SYMBOL: check-vocab-hook
69
70 check-vocab-hook [ [ drop ] ] initialize
71
72 DEFER: require
73
74 <PRIVATE
75
76 SYMBOL: require-when-vocabs
77 require-when-vocabs [ HS{ } clone ] initialize
78
79 SYMBOL: require-when-table
80 require-when-table [ V{ } clone ] initialize
81
82 : load-conditional-requires ( vocab -- )
83     vocab-name require-when-vocabs get in? [
84         require-when-table get [
85             [ [ vocab dup [ source-loaded?>> +done+ = ] when ] all? ] dip
86             [ require ] curry when
87         ] assoc-each
88     ] when ;
89
90 : load-source ( vocab -- )
91     dup check-vocab-hook get call( vocab -- )
92     [
93         +parsing+ >>source-loaded?
94         dup vocab-source-path [ parse-file ] [ [ ] ] if*
95         [ +parsing+ >>source-loaded? ] dip
96         [ % ] [ call( -- ) ] if-bootstrapping
97         +done+ >>source-loaded?
98         load-conditional-requires
99     ] [ ] [ f >>source-loaded? ] cleanup ;
100
101 : load-docs ( vocab -- )
102     load-help? get [
103         [
104             +parsing+ >>docs-loaded?
105             [ vocab-docs-path [ ?run-file ] when* ] keep
106             +done+ >>docs-loaded?
107         ] [ ] [ f >>docs-loaded? ] cleanup
108     ] when drop ;
109
110 PRIVATE>
111
112 : require ( vocab -- )
113     load-vocab drop ;
114
115 : require-when ( if then -- )
116     over [ vocab ] all? [
117         require drop
118     ] [
119         [ drop [ require-when-vocabs get adjoin ] each ]
120         [ 2array require-when-table get push ] 2bi
121     ] if ;
122
123 : reload ( name -- )
124     dup vocab
125     [ [ load-source ] [ load-docs ] bi ]
126     [ require ]
127     ?if ;
128
129 : run ( vocab -- )
130     dup load-vocab vocab-main [
131         execute( -- )
132     ] [
133         "The " write vocab-name write
134         " vocabulary does not define an entry point." print
135         "To define one, refer to \\ MAIN: help" print
136     ] ?if ;
137
138 SYMBOL: blacklist
139
140 <PRIVATE
141
142 : add-to-blacklist ( error vocab -- )
143     vocab-name blacklist get dup [ set-at ] [ 3drop ] if ;
144
145 GENERIC: (load-vocab) ( name -- vocab )
146
147 M: vocab (load-vocab)
148     [
149         dup source-loaded?>> +parsing+ eq? [
150             dup source-loaded?>> [ dup load-source ] unless
151             dup docs-loaded?>> [ dup load-docs ] unless
152         ] unless
153     ] [ [ swap add-to-blacklist ] keep rethrow ] recover ;
154
155 M: vocab-link (load-vocab)
156     vocab-name (load-vocab) ;
157
158 M: string (load-vocab) create-vocab (load-vocab) ;
159
160 PRIVATE>
161
162 [
163     dup vocab-name blacklist get at* [ rethrow ] [
164         drop dup find-vocab-root
165         [ (load-vocab) ] [ dup vocab [ ] [ no-vocab ] ?if ] if
166     ] if
167 ] load-vocab-hook set-global
168
169 M: vocab-spec where vocab-source-path dup [ 1 2array ] when ;