1+ use crate :: persistent_list_map:: PersistentListMap ;
12use crate :: symbol:: Symbol ;
2- use crate :: value:: Value ;
3+ use crate :: var:: Var ;
4+ use crate :: value:: { ToValue , Value } ;
35use std:: cell:: RefCell ;
46use std:: collections:: HashMap ;
57use std:: rc:: Rc ;
@@ -126,12 +128,18 @@ impl Default for Refers {
126128#[ derive( Debug , Clone ) ]
127129pub struct Namespace {
128130 pub name : Symbol ,
129- mappings : RefCell < HashMap < Symbol , Rc < Value > > > ,
130131 pub refers : RefCell < Refers > ,
132+ // @TODO decide to make Var a Rc<Var> ?
133+ // On one hand, its internals (except its ns and name) are Rcs, so cloning is still
134+ // cloning a reference
135+ //
136+ // On the other hand, the Var itself, regardless, lives in one spot and is referenced by many
137+ // This explicitly shows its a reference
138+ mappings : RefCell < HashMap < Symbol , Var > > ,
131139}
132140
133141impl Namespace {
134- fn new ( name : & Symbol , mappings : HashMap < Symbol , Rc < Value > > , refers : Refers ) -> Namespace {
142+ fn new ( name : & Symbol , mappings : HashMap < Symbol , Var > , refers : Refers ) -> Namespace {
135143 Namespace {
136144 name : name. unqualified ( ) ,
137145 mappings : RefCell :: new ( mappings) ,
@@ -155,20 +163,47 @@ impl Namespace {
155163 . replace_with ( |refers| refers. add_referred_namespaces ( namespaces) ) ;
156164 }
157165
166+ //
167+ fn contains_key ( & self , sym : & Symbol ) -> bool {
168+ self . mappings . borrow_mut ( ) . contains_key ( sym)
169+ }
158170 pub fn insert ( & self , sym : & Symbol , val : Rc < Value > ) {
159- self . mappings . borrow_mut ( ) . insert ( sym. unqualified ( ) , val) ;
171+ if !self . contains_key ( sym) {
172+ let var = var ! ( & self . name. name, & sym. name) ;
173+ var. bind_root ( val) ;
174+ var. set_meta ( sym. meta ( ) ) ;
175+ self . mappings
176+ . borrow_mut ( )
177+ . insert ( sym. unqualified ( ) , var) ;
178+ } else {
179+ let mappings = self . mappings . borrow_mut ( ) ;
180+ let var = mappings
181+ . get ( & sym. unqualified ( ) )
182+ . unwrap ( ) ;
183+
184+ var. bind_root ( val) ;
185+ var. set_meta ( sym. meta ( ) ) ;
186+ }
187+ }
188+
189+ pub fn get_var ( & self , sym : & Symbol ) -> Rc < Value > {
190+ match self . mappings . borrow_mut ( ) . get ( & sym. unqualified ( ) ) . map ( |var| var. clone ( ) ) {
191+ Some ( var) => Rc :: new ( Value :: Var ( var) ) ,
192+ None => Rc :: new ( Value :: Condition ( format ! ( "Undefined symbol {}" , sym. name) ) ) ,
193+ }
160194 }
161195
162196 pub fn try_get ( & self , sym : & Symbol ) -> Option < Rc < Value > > {
163197 match self . mappings . borrow_mut ( ) . get ( & sym. unqualified ( ) ) {
164- Some ( val ) => Some ( Rc :: clone ( val ) ) ,
198+ Some ( var ) => Some ( var . deref ( ) ) ,
165199 None => None ,
166200 }
167201 }
202+
168203 pub fn get ( & self , sym : & Symbol ) -> Rc < Value > {
169204 match self . try_get ( sym) {
170205 Some ( val) => val,
171- None => Rc :: new ( Value :: Condition ( format ! ( "1 Undefined symbol {}" , sym. name) ) ) ,
206+ None => Rc :: new ( Value :: Condition ( format ! ( "Undefined symbol {}" , sym. name) ) ) ,
172207 }
173208 }
174209}
@@ -260,7 +295,28 @@ impl Namespaces {
260295 }
261296 }
262297 }
298+ // TODO write this similar to try_get, and rewrite try_get in terms of this
299+ pub fn get_var ( & self , namespace_sym : & Symbol , sym : & Symbol ) -> Rc < Value > {
300+ // When storing / retrieving from namespaces, we want
301+ // namespace_sym unqualified keys
302+ let mut namespace_sym = namespace_sym. unqualified ( ) ;
303+
304+ // @TODO just make it an Optional<String>
305+ // If our sym is namespace qualified, use that as our namespace
306+ if sym. has_ns ( ) {
307+ namespace_sym = Symbol :: intern ( & sym. ns ) ;
308+ }
309+
310+ let sym = sym. unqualified ( ) ;
311+ let namespaces = self . 0 . borrow ( ) ;
312+ let namespace = namespaces. get ( & namespace_sym) ;
263313
314+ match namespace {
315+ Some ( namespace) => namespace. get_var ( & sym) ,
316+ // @TODO should this be a condition or nil?
317+ _ => Rc :: new ( Value :: Condition ( format ! ( "Undefined symbol {}" , sym. name) ) ) ,
318+ }
319+ }
264320 /// Like get, but slightly lower level; returns a None on failure rather than a
265321 /// Value::Condition. See docs for get
266322 pub fn try_get ( & self , namespace_sym : & Symbol , sym : & Symbol ) -> Option < Rc < Value > > {
@@ -313,11 +369,11 @@ impl Namespaces {
313369 // { 'clojure.core ['a 'b 'c] ,
314370 // 'clojure.string ['x 'y 'z]}
315371 // referred_namespace_sym: Symbol::intern("clojure.core"),
316- // referred_syms: vec![Symbol::intern("x "), .. Symbol::intern("z ")]
372+ // referred_syms: vec![Symbol::intern("a "), .. Symbol::intern("c ")]
317373 for ( referred_namespace_sym, referred_syms) in referred_syms_map. iter ( ) {
318374 // Ex: (if we're trying to get, say, '+)
319375 // Do we even refer a '+ from this namespace?
320- // 'clojure.string ['x 'y 'z ] <-- no
376+ // 'clojure.core ['a 'b 'c ] <-- no
321377 // Continue then
322378 if !referred_syms. contains ( & sym) {
323379 continue ;
@@ -710,12 +766,12 @@ mod tests {
710766 namespace. insert ( & Symbol :: intern ( "a" ) , Rc :: new ( Value :: Nil ) ) ;
711767 namespace. insert ( & Symbol :: intern_with_ns ( "ns" , "b" ) , Rc :: new ( Value :: Nil ) ) ;
712768 match & * namespace. get ( & Symbol :: intern ( "a" ) ) {
713- Value :: Condition ( _) => panic ! ( "We are unable to get a symbol we've put into our namespace created with from_sym()" ) ,
769+ Value :: Condition ( _) => panic ! ( "We are unable to get a symbol (a) we've put into our namespace created with from_sym()" ) ,
714770 _ => { }
715771 }
716772
717773 match & * namespace. get ( & Symbol :: intern ( "b" ) ) {
718- Value :: Condition ( _) => panic ! ( "We are unable to get a symbol we've put into our namespace created with from_sym()" ) ,
774+ Value :: Condition ( _) => panic ! ( "We are unable to get a symbol (ns/b) we've put into our namespace created with from_sym()" ) ,
719775 _ => { }
720776 }
721777
0 commit comments