@@ -10,17 +10,17 @@ pub struct Namespace {
10
10
mappings : RefCell < HashMap < Symbol , Rc < Value > > > ,
11
11
}
12
12
impl Namespace {
13
- pub fn new ( name : Symbol , mappings : RefCell < HashMap < Symbol , Rc < Value > > > ) -> Namespace {
14
- Namespace { name, mappings }
13
+ pub fn new ( name : & Symbol , mappings : RefCell < HashMap < Symbol , Rc < Value > > > ) -> Namespace {
14
+ Namespace { name : name . unqualified ( ) , mappings }
15
15
}
16
- pub fn from_sym ( name : Symbol ) -> Namespace {
16
+ pub fn from_sym ( name : & Symbol ) -> Namespace {
17
17
Namespace :: new ( name, RefCell :: new ( HashMap :: new ( ) ) )
18
18
}
19
- pub fn insert ( & self , sym : Symbol , val : Rc < Value > ) {
20
- self . mappings . borrow_mut ( ) . insert ( sym, val) ;
19
+ pub fn insert ( & self , sym : & Symbol , val : Rc < Value > ) {
20
+ self . mappings . borrow_mut ( ) . insert ( sym. unqualified ( ) , val) ;
21
21
}
22
22
pub fn get ( & self , sym : & Symbol ) -> Rc < Value > {
23
- match self . mappings . borrow_mut ( ) . get ( sym) {
23
+ match self . mappings . borrow_mut ( ) . get ( & sym. unqualified ( ) ) {
24
24
Some ( val) => Rc :: clone ( val) ,
25
25
None => Rc :: new ( Value :: Condition ( format ! ( "1 Undefined symbol {}" , sym. name) ) ) ,
26
26
}
@@ -33,13 +33,17 @@ impl Namespaces {
33
33
pub fn new ( ) -> Namespaces {
34
34
Namespaces ( RefCell :: new ( HashMap :: new ( ) ) )
35
35
}
36
- /// Insert a new namespace of name (sym)
37
- pub fn insert ( & self , sym : Symbol , namespace : Namespace ) {
36
+ fn insert ( & self , namespace : Namespace ) {
38
37
// When storing / retrieving from namespaces, we want
39
38
// namespace unqualified keys
40
- let sym = sym. unqualified ( ) ;
41
- self . 0 . borrow_mut ( ) . insert ( sym, namespace) ;
39
+ self . 0 . borrow_mut ( ) . insert ( namespace. name . unqualified ( ) , namespace) ;
42
40
}
41
+ /// Adds a new namespace to internal HashMap (but does
42
+ /// *not* return a Namespace or reference to one)
43
+ pub fn create_namespace ( & self , sym : & Symbol ) {
44
+ self . insert ( Namespace :: from_sym ( sym) ) ;
45
+ }
46
+ /// Insert a new namespace of name (sym)
43
47
pub fn has_namespace ( & self , namespace_sym : & Symbol ) -> bool {
44
48
let namespace_sym = namespace_sym. unqualified ( ) ;
45
49
@@ -50,32 +54,28 @@ impl Namespaces {
50
54
None => false ,
51
55
}
52
56
}
53
- // @TODO Consider writing `sym` as reference here, because we clone it anyways
54
- // Only reason to keep it is `inserts` are pass-by-value here normally,
55
- // since the idea normally is you are literally inserting the keys too
56
- // I'd prefer that consistency, unless we find it has a noticeable
57
- // performance impact
58
57
/// Insert a binding (sym = val) *into* namespace (namespace)
59
- pub fn insert_into_namespace ( & self , namespace_sym : & Symbol , sym : Symbol , val : Rc < Value > ) {
58
+ /// If namespace doesn't exist, create it
59
+ pub fn insert_into_namespace ( & self , namespace_sym : & Symbol , sym : & Symbol , val : Rc < Value > ) {
60
60
let mut namespace_sym = & namespace_sym. unqualified ( ) ;
61
61
// We will only use this if ns isn't ""
62
62
let symbol_namespace_sym = Symbol :: intern ( & sym. ns ) ;
63
63
64
- if sym. ns != "" {
64
+ if sym. has_ns ( ) {
65
65
namespace_sym = & symbol_namespace_sym;
66
66
}
67
67
68
68
let namespaces = self . 0 . borrow ( ) ;
69
69
let namespace = namespaces. get ( namespace_sym) ;
70
70
match namespace {
71
71
Some ( namespace) => {
72
- namespace. insert ( sym. unqualified ( ) , val) ;
72
+ namespace. insert ( sym, val) ;
73
73
}
74
74
None => {
75
75
drop ( namespaces) ;
76
- let namespace = Namespace :: from_sym ( namespace_sym. clone ( ) ) ;
77
- namespace. insert ( sym. unqualified ( ) , val) ;
78
- self . insert ( namespace_sym . unqualified ( ) , namespace) ;
76
+ let namespace = Namespace :: from_sym ( namespace_sym) ;
77
+ namespace. insert ( sym, val) ;
78
+ self . insert ( namespace) ;
79
79
}
80
80
}
81
81
}
@@ -87,7 +87,7 @@ impl Namespaces {
87
87
88
88
// @TODO just make it an Optional<String>
89
89
// If our sym is namespace qualified, use that as our namespace
90
- if sym. ns != "" {
90
+ if sym. has_ns ( ) {
91
91
namespace_sym = Symbol :: intern ( & sym. ns ) ;
92
92
}
93
93
@@ -105,13 +105,145 @@ impl Namespaces {
105
105
106
106
#[ cfg( test) ]
107
107
mod tests {
108
+ // 'Struct' here because its not immediately clear why, when testing this,
109
+ // why the word 'namespace' is repeated and that this is actually specifically
110
+ // a struct
111
+ mod namespace_struct {
112
+ use crate :: namespace:: Namespace ;
113
+ use crate :: symbol:: Symbol ;
114
+ use crate :: value:: Value ;
115
+ use std:: rc:: Rc ;
116
+ use std:: cell:: RefCell ;
117
+ use std:: collections:: HashMap ;
118
+
119
+ #[ test]
120
+ fn new ( ) {
121
+ let namespace = Namespace :: new ( & Symbol :: intern ( "a" ) , RefCell :: new ( HashMap :: new ( ) ) ) ;
122
+ assert_eq ! ( namespace. name, Symbol :: intern( "a" ) ) ;
123
+ assert ! ( namespace. mappings. borrow( ) . is_empty( ) ) ;
124
+ }
125
+
126
+ #[ test]
127
+ fn new_removes_namespace_from_qualified_symbol ( ) {
128
+ let namespace = Namespace :: new ( & Symbol :: intern_with_ns ( "ns" , "a" ) , RefCell :: new ( HashMap :: new ( ) ) ) ;
129
+ assert_eq ! ( namespace. name, Symbol :: intern( "a" ) ) ;
130
+ assert ! ( namespace. name != Symbol :: intern_with_ns( "ns" , "a" ) ) ;
131
+ assert ! ( namespace. mappings. borrow( ) . is_empty( ) ) ;
132
+ }
133
+ #[ test]
134
+ fn new_namespace_starts_empty ( ) {
135
+ let namespace = Namespace :: new ( & Symbol :: intern ( "a" ) , RefCell :: new ( HashMap :: new ( ) ) ) ;
136
+ let namespace2 = Namespace :: new ( & Symbol :: intern_with_ns ( "ns" , "b" ) , RefCell :: new ( HashMap :: new ( ) ) ) ;
137
+ assert ! ( namespace. mappings. borrow( ) . is_empty( ) ) ;
138
+ assert ! ( namespace2. mappings. borrow( ) . is_empty( ) ) ;
139
+ }
140
+
141
+ #[ test]
142
+ fn from_sym ( ) {
143
+ let namespace = Namespace :: from_sym ( & Symbol :: intern_with_ns ( "ns" , "name" ) ) ;
144
+ assert_eq ! ( namespace. name, Symbol :: intern( "name" ) ) ;
145
+ assert ! ( namespace. name != Symbol :: intern_with_ns( "ns" , "name" ) ) ;
146
+ assert ! ( namespace. mappings. borrow( ) . is_empty( ) ) ;
147
+ }
148
+ #[ test]
149
+ fn insert ( ) {
150
+ let namespace = Namespace :: from_sym ( & Symbol :: intern ( "name" ) ) ;
151
+ namespace. insert ( & Symbol :: intern ( "a" ) , Rc :: new ( Value :: Nil ) ) ;
152
+ namespace. insert ( & Symbol :: intern_with_ns ( "ns" , "b" ) , Rc :: new ( Value :: Nil ) ) ;
153
+ assert_eq ! ( namespace. name, Symbol :: intern( "name" ) ) ;
154
+ assert ! ( namespace. name != Symbol :: intern( "ns" ) ) ;
155
+ assert ! ( namespace. name != Symbol :: intern_with_ns( "ns" , "name" ) ) ;
156
+
157
+ namespace. insert ( & Symbol :: intern ( "c" ) , Rc :: new ( Value :: Nil ) ) ;
158
+ match & * namespace. get ( & Symbol :: intern ( "c" ) ) {
159
+ Value :: Condition ( _) => panic ! ( "We are unable to get a symbol we've put into our namespace created with from_sym()" ) ,
160
+ _ => { }
161
+ }
162
+ }
163
+
164
+ #[ test]
165
+ fn get ( ) {
166
+ let namespace = Namespace :: from_sym ( & Symbol :: intern ( "name" ) ) ;
167
+ namespace. insert ( & Symbol :: intern ( "a" ) , Rc :: new ( Value :: Nil ) ) ;
168
+ namespace. insert ( & Symbol :: intern_with_ns ( "ns" , "b" ) , Rc :: new ( Value :: Nil ) ) ;
169
+ match & * namespace. get ( & Symbol :: intern ( "a" ) ) {
170
+ Value :: Condition ( _) => panic ! ( "We are unable to get a symbol we've put into our namespace created with from_sym()" ) ,
171
+ _ => { }
172
+ }
108
173
109
- mod namespaces {
174
+ match & * namespace. get ( & Symbol :: intern ( "b" ) ) {
175
+ Value :: Condition ( _) => panic ! ( "We are unable to get a symbol we've put into our namespace created with from_sym()" ) ,
176
+ _ => { }
177
+ }
178
+
179
+ match & * namespace. get ( & Symbol :: intern ( "ns" ) ) {
180
+ Value :: Condition ( _) => { }
181
+ _ => panic ! ( "We are able to get a symbol whose name is the namespace of another symbol we inserted (and note, that namesapce should be dropped altogether on insert)" ) ,
182
+ }
183
+
184
+ match & * namespace. get ( & Symbol :: intern ( "sassafrass" ) ) {
185
+ Value :: Condition ( _) => { }
186
+ _ => panic ! ( "We are able to get a symbol we didn't insert without a Condition being thrown" ) ,
187
+ }
188
+
189
+ match & * namespace. get ( & Symbol :: intern_with_ns ( "ns" , "b" ) ) {
190
+ Value :: Condition ( _) => panic ! ( "We are unable to get a symbol by trying to get a namespace qualified version of it (the namespace normally should be irrelevant and automatically drop)" ) ,
191
+ _ => { }
192
+ }
193
+
194
+ match & * namespace. get ( & Symbol :: intern_with_ns ( "chicken" , "a" ) ) {
195
+ Value :: Condition ( _) => panic ! ( "We are unable to get a symbol by trying to get a namespace qualified (with a random namespace) version of it (the namespace normally should be irrelevant and automatically drop)" ) ,
196
+ _ => { }
197
+ }
198
+ }
199
+ }
200
+ mod namespaces_newtype {
201
+ use crate :: namespace:: Namespace ;
110
202
use crate :: namespace:: Namespaces ;
111
203
use crate :: symbol:: Symbol ;
112
204
use crate :: value:: Value ;
113
205
use std:: rc:: Rc ;
206
+ fn new ( ) {
207
+ let namespaces = Namespaces :: new ( ) ;
208
+ assert ! ( namespaces. 0 . borrow( ) . is_empty( ) ) ;
209
+ }
210
+ fn insert ( ) {
211
+ let namespaces = Namespaces :: new ( ) ;
212
+ let namespace = Namespace :: from_sym ( & Symbol :: intern ( "clojure.core" ) ) ;
213
+ namespace. insert ( & Symbol :: intern ( "+" ) , Rc :: new ( Value :: Nil ) ) ;
214
+ // Namespace should be dropped; doesn't matter when inserting into
215
+ // a namespace
216
+ namespace. insert ( & Symbol :: intern_with_ns ( "clojure.math" , "+" ) , Rc :: new ( Value :: Nil ) ) ;
217
+ /////////////////////////////////////////////////////////////
218
+ namespaces. insert ( namespace) ;
114
219
220
+ assert_eq ! ( Value :: Nil , * namespaces. get( & Symbol :: intern( "clojure.core" ) , & Symbol :: intern( "+" ) ) ) ;
221
+ assert_eq ! ( Value :: Nil , * namespaces. get( & Symbol :: intern_with_ns( "ns-doesn't-matter" , "clojure.core" ) , & Symbol :: intern( "+" ) ) ) ;
222
+ assert_eq ! ( Value :: Nil , * namespaces. get( & Symbol :: intern_with_ns( "ns-doesn't-matter" , "clojure.core" ) , & Symbol :: intern_with_ns( "ns-still-doesn't-matter" , "+" ) ) ) ;
223
+ //Ie, we should get a Condition, because there is no clojure.math/+
224
+ assert ! ( Value :: Nil != * namespaces. get( & Symbol :: intern( "clojure.math" ) , & Symbol :: intern( "+" ) ) ) ;
225
+ }
226
+ fn has_namespace ( ) {
227
+ let namespaces = Namespaces :: new ( ) ;
228
+ let namespace = Namespace :: from_sym ( & Symbol :: intern ( "clojure.core" ) ) ;
229
+ namespace. insert ( & Symbol :: intern ( "+" ) , Rc :: new ( Value :: Nil ) ) ;
230
+
231
+ assert ! ( namespaces. has_namespace( & Symbol :: intern( "clojure.core" ) ) ) ;
232
+ assert ! ( namespaces. has_namespace( & Symbol :: intern_with_ns( "ns-doesn't-matter" , "clojure.core" ) ) ) ;
233
+ assert ! ( !namespaces. has_namespace( & Symbol :: intern( "+" ) ) ) ;
234
+ // Note; ns-doesn't-matter *isn't* the namespace this time
235
+ assert ! ( !namespaces. has_namespace( & Symbol :: intern_with_ns( "clojure.core" , "ns-doesn't-matter" ) ) ) ;
236
+ }
237
+ fn insert_into_namespace ( ) {
238
+ let namespaces = Namespaces :: new ( ) ;
239
+ namespaces. insert_into_namespace ( & Symbol :: intern ( "clojure.core" ) , & Symbol :: intern ( "+" ) , Rc :: new ( Value :: Nil ) ) ;
240
+ assert ! ( !namespaces. has_namespace( & Symbol :: intern( "random_ns" ) ) ) ;
241
+ assert ! ( namespaces. has_namespace( & Symbol :: intern( "clojure.core" ) ) ) ;
242
+
243
+ assert_eq ! ( Value :: Nil , * namespaces. get( & Symbol :: intern( "clojure.core" ) , & Symbol :: intern( "+" ) ) ) ;
244
+ assert ! ( Value :: Nil != * namespaces. get( & Symbol :: intern( "clojure.core" ) , & Symbol :: intern( "other-sym" ) ) ) ;
245
+ assert ! ( Value :: Nil != * namespaces. get( & Symbol :: intern( "other-ns" ) , & Symbol :: intern( "+" ) ) ) ;
246
+ }
115
247
////////////////////////////////////////////////////////////////////////////////////////////////////
116
248
//
117
249
// pub fn get(&self,namespace_sym: &Symbol,sym: &Symbol) -> Rc<Value>
@@ -139,7 +271,7 @@ mod tests {
139
271
let clojure_core1_plus_1 = Symbol :: intern ( "clojure.core1/+1" ) ;
140
272
namespaces. insert_into_namespace (
141
273
& Symbol :: intern ( "clojure.core1" ) ,
142
- Symbol :: intern ( "+1" ) ,
274
+ & Symbol :: intern ( "+1" ) ,
143
275
Rc :: new ( Value :: Nil ) ,
144
276
) ;
145
277
match & * namespaces. get ( & Symbol :: intern ( "clojure.your" ) , & clojure_core1_plus_1) {
@@ -162,7 +294,7 @@ mod tests {
162
294
let clojure_core_plus = Symbol :: intern ( "clojure.core/+" ) ;
163
295
namespaces. insert_into_namespace (
164
296
& Symbol :: intern ( "clojure.core" ) ,
165
- Symbol :: intern ( "+" ) ,
297
+ & Symbol :: intern ( "+" ) ,
166
298
Rc :: new ( Value :: Nil ) ,
167
299
) ;
168
300
// Really means get +/+, but is overwritten to mean get clojure.core/+
@@ -185,7 +317,7 @@ mod tests {
185
317
let plus_2 = Symbol :: intern ( "+2" ) ;
186
318
namespaces. insert_into_namespace (
187
319
& Symbol :: intern ( "core2" ) ,
188
- Symbol :: intern ( "+2" ) ,
320
+ & Symbol :: intern ( "+2" ) ,
189
321
Rc :: new ( Value :: Nil ) ,
190
322
) ;
191
323
// Get intern("core2/+2")
@@ -208,7 +340,7 @@ mod tests {
208
340
let namespaces = Namespaces :: new ( ) ;
209
341
namespaces. insert_into_namespace (
210
342
& Symbol :: intern ( "core2" ) ,
211
- Symbol :: intern ( "+2" ) ,
343
+ & Symbol :: intern ( "+2" ) ,
212
344
Rc :: new ( Value :: Nil ) ,
213
345
) ;
214
346
0 commit comments