@@ -23,22 +23,48 @@ pub struct EnvironmentVal {
2323 namespaces : Namespaces ,
2424}
2525impl EnvironmentVal {
26+ // @TODO is this wrapper really necessary, or is it just inviting an invariant break?
27+ /// Note; do not use. Does not enforce the invariant that namespace exist
28+ /// Use change_or_create_namespace instead
2629 fn change_namespace ( & self , name : Symbol ) {
2730 self . curr_ns_sym . replace ( name) ;
2831 }
29- fn insert_into_namespace ( & self , namespace : & Symbol , sym : Symbol , val : Rc < Value > ) {
30- self . namespaces . insert_into_namespace ( namespace, & sym, val) ;
32+ fn change_or_create_namespace ( & self , symbol : & Symbol ) {
33+ if self . has_namespace ( symbol) {
34+ self . change_namespace ( symbol. unqualified ( ) ) ;
35+ } else {
36+ self . create_namespace ( symbol) ;
37+ self . change_namespace ( symbol. unqualified ( ) ) ;
38+ }
39+ }
40+ fn add_referred_syms ( & self , namespace_sym : & Symbol , syms : HashMap < Symbol , Vec < Symbol > > ) {
41+ self . namespaces . add_referred_syms ( namespace_sym, syms) ;
42+ }
43+ fn add_referred_namespace ( & self , namespace_sym : & Symbol , referred_namespace_sym : & Symbol ) {
44+ self . namespaces
45+ . add_referred_namespace ( namespace_sym, referred_namespace_sym) ;
46+ }
47+ fn insert_into_namespace ( & self , namespace_sym : & Symbol , sym : Symbol , val : Rc < Value > ) {
48+ self . namespaces
49+ . insert_into_namespace ( namespace_sym, & sym, val) ;
3150 }
3251 fn insert_into_current_namespace ( & self , sym : Symbol , val : Rc < Value > ) {
3352 self . namespaces
3453 . insert_into_namespace ( & * self . curr_ns_sym . borrow ( ) , & sym, val) ;
3554 }
55+ fn has_namespace ( & self , namespace : & Symbol ) -> bool {
56+ self . namespaces . has_namespace ( namespace)
57+ }
3658 fn get_from_namespace ( & self , namespace : & Symbol , sym : & Symbol ) -> Rc < Value > {
3759 self . namespaces . get ( namespace, sym)
3860 }
3961 fn get_current_namespace ( & self ) -> Symbol {
4062 self . curr_ns_sym . borrow ( ) . clone ( )
4163 }
64+
65+ fn create_namespace ( & self , symbol : & Symbol ) {
66+ self . namespaces . create_namespace ( symbol) ;
67+ }
4268 // @TODO as mentioned, we've been working with a memory model where values exist
4369 // in our system once-ish and we reference them all over with Rc<..>
4470 // Look into possibly working this into that (if its even significant);
@@ -68,16 +94,60 @@ pub enum Environment {
6894}
6995use Environment :: * ;
7096impl Environment {
71- pub fn change_namespace ( & self , symbol : Symbol ) {
72- let symbol = symbol. unqualified ( ) ;
73-
97+ pub fn has_namespace ( & self , symbol : & Symbol ) -> bool {
7498 match self . get_main_environment ( ) {
75- MainEnvironment ( EnvironmentVal { curr_ns_sym, .. } ) => {
76- curr_ns_sym. replace ( symbol) ;
99+ MainEnvironment ( env_val) => env_val. has_namespace ( symbol) ,
100+ LocalEnvironment ( ..) => panic ! (
101+ "get_main_environment() returns LocalEnvironment,\
102+ but by definition should only return MainEnvironment"
103+ ) ,
104+ }
105+ }
106+ pub fn add_referred_syms ( & self , namespace_sym : & Symbol , syms : HashMap < Symbol , Vec < Symbol > > ) {
107+ match self . get_main_environment ( ) {
108+ MainEnvironment ( env_val) => {
109+ env_val. add_referred_syms ( namespace_sym, syms) ;
77110 }
78111 LocalEnvironment ( ..) => panic ! (
79112 "get_main_environment() returns LocalEnvironment,\
80- but by definition should only return MainEnvironment"
113+ but by definition should only return MainEnvironment"
114+ ) ,
115+ }
116+ }
117+ pub fn add_referred_syms_to_curr_namespace ( & self , syms : HashMap < Symbol , Vec < Symbol > > ) {
118+ match self . get_main_environment ( ) {
119+ MainEnvironment ( env_val) => {
120+ let namespace_sym = self . get_current_namespace ( ) ;
121+ env_val. add_referred_syms ( & namespace_sym, syms) ;
122+ }
123+ LocalEnvironment ( ..) => panic ! (
124+ "get_main_environment() returns LocalEnvironment,\
125+ but by definition should only return MainEnvironment"
126+ ) ,
127+ }
128+ }
129+ pub fn add_referred_namespace_to_curr_namespace ( & self , referred_namespace_sym : & Symbol ) {
130+ match self . get_main_environment ( ) {
131+ MainEnvironment ( env_val) => {
132+ let namespace_sym = self . get_current_namespace ( ) ;
133+ env_val. add_referred_namespace ( & namespace_sym, referred_namespace_sym) ;
134+ }
135+ LocalEnvironment ( ..) => panic ! (
136+ "get_main_environment() returns LocalEnvironment,\
137+ but by definition should only return MainEnvironment"
138+ ) ,
139+ }
140+ }
141+ /// Changes the current namespace, or creates one first if
142+ /// namespace doesn't already exist
143+ pub fn change_or_create_namespace ( & self , symbol : & Symbol ) {
144+ match self . get_main_environment ( ) {
145+ MainEnvironment ( env_val) => {
146+ env_val. change_or_create_namespace ( symbol) ;
147+ }
148+ LocalEnvironment ( ..) => panic ! (
149+ "get_main_environment() returns LocalEnvironment,\
150+ but by definition should only return MainEnvironment"
81151 ) ,
82152 }
83153 }
@@ -155,14 +225,11 @@ impl Environment {
155225 MainEnvironment ( env_val) => {
156226 // If we've recieved a qualified symbol like
157227 // clojure.core/+
158- if sym. ns != "" {
228+ if sym. has_ns ( ) {
159229 // Use that namespace
160230 env_val. get_from_namespace ( & Symbol :: intern ( & sym. ns ) , sym)
161231 } else {
162- env_val. get_from_namespace (
163- & env_val. get_current_namespace ( ) ,
164- & Symbol :: intern ( & sym. name ) ,
165- )
232+ env_val. get_from_namespace ( & env_val. get_current_namespace ( ) , & sym)
166233 }
167234 }
168235 LocalEnvironment ( parent_env, mappings) => {
@@ -239,10 +306,11 @@ impl Environment {
239306 let eval_fn = rust_core:: EvalFn :: new ( Rc :: clone ( & environment) ) ;
240307 let ns_macro = rust_core:: NsMacro :: new ( Rc :: clone ( & environment) ) ;
241308 let load_file_fn = rust_core:: LoadFileFn :: new ( Rc :: clone ( & environment) ) ;
309+ let refer_fn = rust_core:: ReferFn :: new ( Rc :: clone ( & environment) ) ;
242310 // @TODO after we merge this with all the other commits we have,
243311 // just change all the `insert`s here to use insert_in_namespace
244312 // I prefer explicity and the non-dependence-on-environmental-factors
245- environment. change_namespace ( Symbol :: intern ( "clojure.core" ) ) ;
313+ environment. change_or_create_namespace ( & Symbol :: intern ( "clojure.core" ) ) ;
246314
247315 environment. insert ( Symbol :: intern ( "+" ) , add_fn. to_rc_value ( ) ) ;
248316 environment. insert ( Symbol :: intern ( "-" ) , subtract_fn. to_rc_value ( ) ) ;
@@ -402,6 +470,8 @@ impl Environment {
402470 environment. insert ( Symbol :: intern ( "read-line" ) , read_line_fn. to_rc_value ( ) ) ;
403471
404472 environment. insert ( Symbol :: intern ( "=" ) , equals_fn. to_rc_value ( ) ) ;
473+ environment. insert ( Symbol :: intern ( "refer" ) , refer_fn. to_rc_value ( ) ) ;
474+
405475 //
406476 // Read in clojure.core
407477 //
@@ -411,7 +481,7 @@ impl Environment {
411481 let _ = Repl :: new ( Rc :: clone ( & environment) ) . try_eval_file ( "./src/clojure/string.clj" ) ;
412482
413483 // We can add this back once we have requires
414- // environment.change_namespace (Symbol::intern("user"));
484+ // environment.change_or_create_namespace (Symbol::intern("user"));
415485
416486 environment
417487 }
@@ -437,11 +507,11 @@ mod tests {
437507
438508 assert_eq ! ( Symbol :: intern( "user" ) , env_val. get_current_namespace( ) ) ;
439509
440- env_val. change_namespace ( Symbol :: intern ( "core" ) ) ;
510+ env_val. change_or_create_namespace ( & Symbol :: intern ( "core" ) ) ;
441511 assert_eq ! ( Symbol :: intern( "core" ) , env_val. get_current_namespace( ) ) ;
442512
443513 // @TODO add this invariant back next, and remove this comment; 5.9.2020
444- // env_val.change_namespace (Symbol::intern_with_ns("not-ns","ns"));
514+ // env_val.change_or_create_namespace (Symbol::intern_with_ns("not-ns","ns"));
445515 // assert_eq!(Symbol::intern("ns"),env_val.get_current_namespace())
446516
447517 // @TODO add case for local environment
0 commit comments