@@ -10,17 +10,17 @@ pub struct Namespace {
1010 mappings : RefCell < HashMap < Symbol , Rc < Value > > > ,
1111}
1212impl 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 }
1515 }
16- pub fn from_sym ( name : Symbol ) -> Namespace {
16+ pub fn from_sym ( name : & Symbol ) -> Namespace {
1717 Namespace :: new ( name, RefCell :: new ( HashMap :: new ( ) ) )
1818 }
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) ;
2121 }
2222 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 ( ) ) {
2424 Some ( val) => Rc :: clone ( val) ,
2525 None => Rc :: new ( Value :: Condition ( format ! ( "1 Undefined symbol {}" , sym. name) ) ) ,
2626 }
@@ -33,13 +33,17 @@ impl Namespaces {
3333 pub fn new ( ) -> Namespaces {
3434 Namespaces ( RefCell :: new ( HashMap :: new ( ) ) )
3535 }
36- /// Insert a new namespace of name (sym)
37- pub fn insert ( & self , sym : Symbol , namespace : Namespace ) {
36+ fn insert ( & self , namespace : Namespace ) {
3837 // When storing / retrieving from namespaces, we want
3938 // 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) ;
4240 }
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)
4347 pub fn has_namespace ( & self , namespace_sym : & Symbol ) -> bool {
4448 let namespace_sym = namespace_sym. unqualified ( ) ;
4549
@@ -50,32 +54,28 @@ impl Namespaces {
5054 None => false ,
5155 }
5256 }
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
5857 /// 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 > ) {
6060 let mut namespace_sym = & namespace_sym. unqualified ( ) ;
6161 // We will only use this if ns isn't ""
6262 let symbol_namespace_sym = Symbol :: intern ( & sym. ns ) ;
6363
64- if sym. ns != "" {
64+ if sym. has_ns ( ) {
6565 namespace_sym = & symbol_namespace_sym;
6666 }
6767
6868 let namespaces = self . 0 . borrow ( ) ;
6969 let namespace = namespaces. get ( namespace_sym) ;
7070 match namespace {
7171 Some ( namespace) => {
72- namespace. insert ( sym. unqualified ( ) , val) ;
72+ namespace. insert ( sym, val) ;
7373 }
7474 None => {
7575 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) ;
7979 }
8080 }
8181 }
@@ -87,7 +87,7 @@ impl Namespaces {
8787
8888 // @TODO just make it an Optional<String>
8989 // If our sym is namespace qualified, use that as our namespace
90- if sym. ns != "" {
90+ if sym. has_ns ( ) {
9191 namespace_sym = Symbol :: intern ( & sym. ns ) ;
9292 }
9393
@@ -105,13 +105,145 @@ impl Namespaces {
105105
106106#[ cfg( test) ]
107107mod 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+ }
108173
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 ;
110202 use crate :: namespace:: Namespaces ;
111203 use crate :: symbol:: Symbol ;
112204 use crate :: value:: Value ;
113205 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) ;
114219
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+ }
115247 ////////////////////////////////////////////////////////////////////////////////////////////////////
116248 //
117249 // pub fn get(&self,namespace_sym: &Symbol,sym: &Symbol) -> Rc<Value>
@@ -139,7 +271,7 @@ mod tests {
139271 let clojure_core1_plus_1 = Symbol :: intern ( "clojure.core1/+1" ) ;
140272 namespaces. insert_into_namespace (
141273 & Symbol :: intern ( "clojure.core1" ) ,
142- Symbol :: intern ( "+1" ) ,
274+ & Symbol :: intern ( "+1" ) ,
143275 Rc :: new ( Value :: Nil ) ,
144276 ) ;
145277 match & * namespaces. get ( & Symbol :: intern ( "clojure.your" ) , & clojure_core1_plus_1) {
@@ -162,7 +294,7 @@ mod tests {
162294 let clojure_core_plus = Symbol :: intern ( "clojure.core/+" ) ;
163295 namespaces. insert_into_namespace (
164296 & Symbol :: intern ( "clojure.core" ) ,
165- Symbol :: intern ( "+" ) ,
297+ & Symbol :: intern ( "+" ) ,
166298 Rc :: new ( Value :: Nil ) ,
167299 ) ;
168300 // Really means get +/+, but is overwritten to mean get clojure.core/+
@@ -185,7 +317,7 @@ mod tests {
185317 let plus_2 = Symbol :: intern ( "+2" ) ;
186318 namespaces. insert_into_namespace (
187319 & Symbol :: intern ( "core2" ) ,
188- Symbol :: intern ( "+2" ) ,
320+ & Symbol :: intern ( "+2" ) ,
189321 Rc :: new ( Value :: Nil ) ,
190322 ) ;
191323 // Get intern("core2/+2")
@@ -208,7 +340,7 @@ mod tests {
208340 let namespaces = Namespaces :: new ( ) ;
209341 namespaces. insert_into_namespace (
210342 & Symbol :: intern ( "core2" ) ,
211- Symbol :: intern ( "+2" ) ,
343+ & Symbol :: intern ( "+2" ) ,
212344 Rc :: new ( Value :: Nil ) ,
213345 ) ;
214346
0 commit comments