Commits

Taegyoon Kim committed bcdb3ab

v1.6: Uses shared_ptr<node>. (fib 30) is 3.5x faster.

Comments (0)

Files changed (5)

 all: paren
 
 paren: paren.cpp libparen.cpp libparen.h
-	g++ -s -Wall -O3 -o paren paren.cpp libparen.cpp
+	g++ -std=c++0x -s -Wall -O3 -o paren paren.cpp libparen.cpp
 
 clean:
 	rm -f paren paren.exe
 ```
 (set maxP 0)
 (for i 100 999 1
-  (for j 100 999 1	
+  (for j i 999 1
     (set p (* i j))
     (set ps (string p))
     (set len (strlen ps))
         init();
     }
 
+	snode make_snode(const node& n) {
+		return make_shared<node>(n);
+	}
+
     node::node(): type(T_NIL) {}
     node::node(int a): type(T_INT), v_int(a) {}
     node::node(double a): type(T_DOUBLE), v_double(a) {}
     node::node(bool a): type(T_BOOL), v_bool(a) {}    
     node::node(const string &a): type(T_STRING), v_string(a) {}
-    node::node(const vector<node> &a): type(T_LIST), v_list(a) {}
-    node nil;
+    node::node(const vector<snode> &a): type(T_LIST), v_list(a) {}
+	snode node_true(make_snode(node(true)));
+	snode node_false(make_snode(node(false)));    
+	snode node_0(make_snode(node(0)));
+	snode node_1(make_snode(node(1)));
+	snode nil(make_snode(node()));	
 
     inline int node::to_int() {
         switch (type) {
         case T_LIST:
             {
                 ret = '(';
-                for (vector<node>::iterator iter = v_list.begin(); iter != v_list.end(); iter++) {
+                for (vector<snode>::iterator iter = v_list.begin(); iter != v_list.end(); iter++) {
                     if (iter != v_list.begin()) ret += ' ';
-                    ret += iter->to_string();
+                    ret += (*iter)->to_string();
                 }
                 ret += ')';
                 break;
         vector<string> tokens;
     public:
         parser(const vector<string> &tokens): pos(0), tokens(tokens) {}
-        vector<node> parse() {
-            vector<node> ret;
+        vector<snode> parse() {
+            vector<snode> ret;
             int last = tokens.size() - 1;
             for (;pos <= last; pos++) {
                 string tok = tokens.at(pos);
                 if (tok.at(0) == '"') { // double-quoted string
-                    ret.push_back(node(tok.substr(1)));
+                    ret.push_back(make_snode(tok.substr(1)));
                 }
                 else if (tok == "(") { // list
                     pos++;
-                    ret.push_back(node(parse()));
+                    ret.push_back(make_snode(parse()));
                 }
                 else if (tok == ")") { // end of list
                     break;
                 }
                 else if (isdigit(tok.at(0)) || (tok.at(0) == '-' && tok.length() >= 2 && isdigit(tok.at(1)))) { // number
                     if (tok.find('.') != string::npos || tok.find('e') != string::npos) { // double
-                        ret.push_back(node(atof(tok.c_str())));
+                        ret.push_back(make_snode(atof(tok.c_str())));
                     } else {
-                        ret.push_back(node(atoi(tok.c_str())));
+                        ret.push_back(make_snode(atoi(tok.c_str())));
                     }
                 } else { // symbol
                     node n;
                     n.type = node::T_SYMBOL;
                     n.v_string = tok;
-					n.p_node = NULL;
+//					n.p_node = NULL;
 					n.code = ToCode(tok);
-                    ret.push_back(n);
+                    ret.push_back(make_snode(n));
                 }
             }
             return ret;
         }        
     };
     
-    vector<node> paren::parse(const string &s) {
+    vector<snode> paren::parse(const string &s) {
         return parser(tokenize(s)).parse();
     }
 
     environment::environment(): outer(NULL) {}
     environment::environment(environment *outer): outer(outer) {}    
 
-    node &environment::get(int code) {
-        map<int, node>::iterator found = env.find(code);
+    snode environment::get(int code) {
+        map<int, snode>::iterator found = env.find(code);
         if (found != env.end()) {
             return found->second;
         }
         }
     }
 
-	node &environment::get(node &k) {
-		//return get(k.code);
-		if (k.p_node != NULL) { // cached
-			return *k.p_node;
-		} else {
-			return *(k.p_node = &get(k.code)); // make cache
-		}
+	snode environment::get(snode &k) {
+		return get(k->code);
+		//if (k->p_node != NULL) { // cached
+		//	return make_snode(*k->p_node);
+		//} else {
+		//	return make_snode(*(k->p_node = get(k->code).get())); // make cache
+		//}
 	}
 
-	node &environment::set(node &k, node &v) {
-		//return env[k.code] = v;
-		if (k.p_node != NULL) { // cached
-			*k.p_node = v;
-		} else {
-			k.p_node = &(env[k.code] = v); // make cache
-		}
-		return *k.p_node;
+	snode environment::set(snode &k, snode &v) {
+		return env[k->code] = v;
+		//if (k->p_node != NULL) { // cached
+		//	*k->p_node = *v;
+		//} else {
+		//	k->p_node = (env[k->code] = v).get(); // make cache
+		//}
+		//return make_snode(*k->p_node);
 	}
 
-    node builtin(int b) {
-        node n(b);
-        n.type = node::T_BUILTIN;
+    snode builtin(int b) {
+        snode n(make_snode(b));
+        n->type = node::T_BUILTIN;
         return n;
     }
 
-    node fn(node n, environment *outer_env) {
-        node n2(n);
-        n2.type = node::T_FN;
-		n2.outer_env = outer_env;
+    snode fn(snode n, environment *outer_env) {
+        snode n2(n);
+        n2->type = node::T_FN;
+		n2->outer_env = outer_env;
         return n2;
     }
 
-    map<string, vector<node> > macros;
+    map<string, vector<snode> > macros;
 
-    node apply_macro(node body, map<string, node> vars) {
-        if (body.type == node::T_LIST) {            
-            vector<node> &bvec = body.v_list;
-            vector<node> ret;            
+    snode apply_macro(snode body, map<string, snode> vars) {
+        if (body->type == node::T_LIST) {            
+            vector<snode> &bvec = body->v_list;
+            vector<snode> ret;            
             for (unsigned int i = 0; i < bvec.size(); i++) {
-                node b = bvec.at(i);
-                if (b.v_string == "...") {
-                    node &vargs = vars[b.v_string];
-                    ret.insert(ret.end(), vargs.v_list.begin(), vargs.v_list.end());                    
+                snode b = bvec.at(i);
+                if (b->v_string == "...") {
+                    snode &vargs = vars[b->v_string];
+                    ret.insert(ret.end(), vargs->v_list.begin(), vargs->v_list.end());                    
                 } else ret.push_back(apply_macro(bvec.at(i), vars));
             }
-            return node(ret);
+            return make_snode(ret);
         } else {
-            string bstr = body.v_string;
+            string &bstr = body->v_string;
             if (vars.find(bstr) != vars.end()) return vars[bstr]; else return body;
         }
     }
 
-    node macroexpand(node n) {        
-        vector<node> nList = n.v_list;
-        if (macros.find(nList[0].v_string) != macros.end()) {            
-            vector<node> &macro = macros[nList[0].v_string];
-            map<string, node> macrovars;
-            vector<node> &argsyms = macro[0].v_list;            
+    snode macroexpand(snode n) {        
+        vector<snode> nList = n->v_list;
+        if (macros.find(nList[0]->v_string) != macros.end()) {            
+            vector<snode> &macro = macros[nList[0]->v_string];
+            map<string, snode> macrovars;
+            vector<snode> &argsyms = macro[0]->v_list;            
             for (unsigned int i = 0; i < argsyms.size(); i++) {
-                string argsym = argsyms.at(i).v_string;
+                string argsym = argsyms.at(i)->v_string;
                 if (argsym == "...") {
-                    vector<node> ellipsis;
-                    node n2(ellipsis);                    
-                    vector<node> &ellipsis2 = n2.v_list;
+                    vector<snode> ellipsis;
+                    snode n2(make_snode(ellipsis));
+                    vector<snode> &ellipsis2 = n2->v_list;
                     for (unsigned int i2 = i + 1; i2 < nList.size(); i2++)
                         ellipsis2.push_back(nList.at(i2));
                     macrovars[argsym] = n2;
                     break;
                 } else {
-                    macrovars[argsyms.at(i).v_string] = nList.at(i+1);                    
+                    macrovars[argsyms.at(i)->v_string] = nList.at(i+1);                    
                 }
             }
             return apply_macro(macro[1], macrovars);
             return n;
     }
 
-    node paren::compile(node &n) {
-        switch (n.type) {
+    snode paren::compile(snode &n) {
+        switch (n->type) {
         case node::T_LIST: // function (FUNCTION ARGUMENT ..)
             {
-				if (n.v_list.size() == 0) return nil;
-                node func = compile(n.v_list[0]);                
-                if (func.type == node::T_SYMBOL && func.v_string == "defmacro") { // (defmacro add (a b) (+ a b)) ; define macro
-                    vector<node> v;
-                    v.push_back(n.v_list[2]);
-                    v.push_back(n.v_list[3]);                        
-                    macros[n.v_list[1].v_string] = v;
+				if (n->v_list.size() == 0) return nil;
+                snode func = compile(n->v_list[0]);                
+                if (func->type == node::T_SYMBOL && func->v_string == "defmacro") { // (defmacro add (a b) (+ a b)) ; define macro
+                    vector<snode> v;
+                    v.push_back(n->v_list[2]);
+                    v.push_back(n->v_list[3]);                        
+                    macros[n->v_list[1]->v_string] = v;
                     return nil;
                 } else {
-                    if (macros.find(func.v_string) != macros.end()) {
-						node expanded = macroexpand(n);
+                    if (macros.find(func->v_string) != macros.end()) {
+						snode expanded = macroexpand(n);
                         return compile(expanded);
                     } else {
-                        vector<node> r;
-                        for (vector<node>::iterator i = n.v_list.begin(); i != n.v_list.end(); i++) {
+                        vector<snode> r;
+                        for (vector<snode>::iterator i = n->v_list.begin(); i != n->v_list.end(); i++) {
                             r.push_back(compile(*i));
                         }
-                        return node(r);
+                        return make_snode(r);
                     } 
                 }
             }
         }
     }
 
-    node paren::eval(node &n, environment &env) {
-        switch (n.type) {
+    snode paren::eval(snode &n, environment &env) {
+        switch (n->type) {
         case node::T_NIL:
         case node::T_INT:
         case node::T_DOUBLE:
             }
         case node::T_SYMBOL:
             {
-				node &n2 = env.get(n);
-                if (n2.type != node::T_NIL) {
+				snode n2 = env.get(n);
+                if (n2->type != node::T_NIL) {
                     return n2;
 				}
                 else {
-                    cerr << "Unknown variable: " << n.v_string << endl;
+                    cerr << "Unknown variable: " << n->v_string << endl;
                     return nil;
                 }
                 
             }
         case node::T_LIST: // function (FUNCTION ARGUMENT ..)
             {
-                node func = eval(n.v_list[0], env);
+                node &func = *eval(n->v_list[0], env);
                 int builtin = -1;
                 if (func.type == node::T_BUILTIN) {
                     builtin = func.v_int;
                     switch(builtin) {
                         case node::PLUS: // (+ X ..)
                             {
-                                int len = n.v_list.size();
-                                if (len <= 1) return node(0);
-                                node first = eval(n.v_list[1], env);
-                                if (first.type == node::T_INT) {
-                                    int sum = first.v_int;
-                                    for (vector<node>::iterator i = n.v_list.begin() + 2; i != n.v_list.end(); i++) {
-                                        sum += eval(*i, env).to_int();
+                                int len = n->v_list.size();
+                                if (len <= 1) return node_0;
+                                snode first = eval(n->v_list[1], env);
+                                if (first->type == node::T_INT) {
+                                    int sum = first->v_int;
+                                    for (vector<snode>::iterator i = n->v_list.begin() + 2; i != n->v_list.end(); i++) {
+                                        sum += eval(*i, env)->to_int();
                                     }
-                                    return node(sum);
+                                    return make_snode(sum);
                                 }
                                 else {
-                                    double sum = first.v_double;
-                                    for (vector<node>::iterator i = n.v_list.begin() + 2; i != n.v_list.end(); i++) {
-                                        sum += eval(*i, env).to_double();
+                                    double sum = first->v_double;
+                                    for (vector<snode>::iterator i = n->v_list.begin() + 2; i != n->v_list.end(); i++) {
+                                        sum += eval(*i, env)->to_double();
                                     }
-                                    return node(sum);
+                                    return make_snode(sum);
                                 }
                             }
                         case node::MINUS: // (- X ..)
                             {
-                                int len = n.v_list.size();
-                                if (len <= 1) return node(0);
-                                node first = eval(n.v_list[1], env);
+                                int len = n->v_list.size();
+                                if (len <= 1) return node_0;
+                                node &first = *eval(n->v_list[1], env);
                                 if (first.type == node::T_INT) {
                                     int sum = first.v_int;
-                                    for (vector<node>::iterator i = n.v_list.begin() + 2; i != n.v_list.end(); i++) {
-                                        sum -= eval(*i, env).to_int();
+                                    for (vector<snode>::iterator i = n->v_list.begin() + 2; i != n->v_list.end(); i++) {
+                                        sum -= eval(*i, env)->to_int();
                                     }
-                                    return node(sum);
+                                    return make_snode(sum);
                                 }
                                 else {
                                     double sum = first.v_double;
-                                    for (vector<node>::iterator i = n.v_list.begin() + 2; i != n.v_list.end(); i++) {
-                                        sum -= eval(*i, env).to_double();
+                                    for (vector<snode>::iterator i = n->v_list.begin() + 2; i != n->v_list.end(); i++) {
+                                        sum -= eval(*i, env)->to_double();
                                     }
-                                    return node(sum);
+                                    return make_snode(sum);
                                 }
                             }
                         case node::MUL: // (* X ..)
                             {
-                                int len = n.v_list.size();
-                                if (len <= 1) return node(1);
-                                node first = eval(n.v_list[1], env);
+                                int len = n->v_list.size();
+                                if (len <= 1) return node_1;
+                                node &first = *eval(n->v_list[1], env);
                                 if (first.type == node::T_INT) {
                                     int sum = first.v_int;
-                                    for (vector<node>::iterator i = n.v_list.begin() + 2; i != n.v_list.end(); i++) {
-                                        sum *= eval(*i, env).to_int();
+                                    for (vector<snode>::iterator i = n->v_list.begin() + 2; i != n->v_list.end(); i++) {
+                                        sum *= eval(*i, env)->to_int();
                                     }
-                                    return node(sum);
+                                    return make_snode(sum);
                                 }
                                 else {
                                     double sum = first.v_double;
-                                    for (vector<node>::iterator i = n.v_list.begin() + 2; i != n.v_list.end(); i++) {
-                                        sum *= eval(*i, env).to_double();
+                                    for (vector<snode>::iterator i = n->v_list.begin() + 2; i != n->v_list.end(); i++) {
+                                        sum *= eval(*i, env)->to_double();
                                     }
-                                    return node(sum);
+                                    return make_snode(sum);
                                 }
                             }
                         case node::DIV: // (/ X ..)
                             {
-                                int len = n.v_list.size();
-                                if (len <= 1) return node(1);
-                                node first = eval(n.v_list[1], env);
+                                int len = n->v_list.size();
+                                if (len <= 1) return node_1;
+                                node &first = *eval(n->v_list[1], env);
                                 if (first.type == node::T_INT) {
                                     int acc = first.v_int;
-                                    for (vector<node>::iterator i = n.v_list.begin() + 2; i != n.v_list.end(); i++) {
-                                        acc /= eval(*i, env).to_int();
+                                    for (vector<snode>::iterator i = n->v_list.begin() + 2; i != n->v_list.end(); i++) {
+                                        acc /= eval(*i, env)->to_int();
                                     }
-                                    return node(acc);
+                                    return make_snode(acc);
                                 }
                                 else {
                                     double acc = first.v_double;
-                                    for (vector<node>::iterator i = n.v_list.begin() + 2; i != n.v_list.end(); i++) {
-                                        acc /= eval(*i, env).to_double();
+                                    for (vector<snode>::iterator i = n->v_list.begin() + 2; i != n->v_list.end(); i++) {
+                                        acc /= eval(*i, env)->to_double();
                                     }
-                                    return node(acc);
+                                    return make_snode(acc);
                                 }
                             }
                         case node::CARET: { // (^ BASE EXPONENT)
-                            return node(pow(eval(n.v_list[1], env).to_double(), eval(n.v_list[2], env).to_double()));}
+                            return make_snode(pow(eval(n->v_list[1], env)->to_double(), eval(n->v_list[2], env)->to_double()));}
                         case node::PERCENT: { // (% DIVIDEND DIVISOR)
-                            return node(eval(n.v_list[1], env).to_int() % eval(n.v_list[2], env).to_int());}
+                            return make_snode(eval(n->v_list[1], env)->to_int() % eval(n->v_list[2], env)->to_int());}
                         case node::SQRT: { // (sqrt X)
-                            return node(sqrt(eval(n.v_list[1], env).to_double()));}
+                            return make_snode(sqrt(eval(n->v_list[1], env)->to_double()));}
                         case node::INC: { // (inc X)
-                                int len = n.v_list.size();
-                                if (len <= 1) return node(0);
-                                node first = eval(n.v_list[1], env);
+                                int len = n->v_list.size();
+                                if (len <= 1) return make_snode(0);
+                                node &first = *eval(n->v_list[1], env);
                                 if (first.type == node::T_INT) {
-                                    return node(first.v_int + 1);
+                                    return make_snode(first.v_int + 1);
                                 }
                                 else {
-                                    return node(first.v_double + 1.0);
+                                    return make_snode(first.v_double + 1.0);
                                 }
                             }
                         case node::DEC: { // (dec X)
-                                int len = n.v_list.size();
-                                if (len <= 1) return node(0);
-                                node first = eval(n.v_list[1], env);
+                                int len = n->v_list.size();
+                                if (len <= 1) return make_snode(0);
+                                node &first = *eval(n->v_list[1], env);
                                 if (first.type == node::T_INT) {
-                                    return node(first.v_int - 1);
+                                    return make_snode(first.v_int - 1);
                                 }
                                 else {
-                                    return node(first.v_double - 1.0);
+                                    return make_snode(first.v_double - 1.0);
                                 }
                             }
                         case node::PLUSPLUS: { // (++ X)
-                                int len = n.v_list.size();
-                                if (len <= 1) return node(0);
-								node &first = env.get(n.v_list[1]);
-                                if (first.type == node::T_INT) {
-									first.v_int++;
+                                int len = n->v_list.size();
+                                if (len <= 1) return make_snode(0);
+								snode first = env.get(n->v_list[1]);
+                                if (first->type == node::T_INT) {
+									first->v_int++;
                                     return first;
                                 }
                                 else {
-									first.v_double++;
+									first->v_double++;
                                     return first;
                                 }
                             }
                         case node::MINUSMINUS: { // (-- X)
-                                int len = n.v_list.size();
-                                if (len <= 1) return node(0);
-								node &first = env.get(n.v_list[1]);
-                                if (first.type == node::T_INT) {
-									first.v_int--;
+                                int len = n->v_list.size();
+                                if (len <= 1) return make_snode(0);
+								snode first = env.get(n->v_list[1]);
+                                if (first->type == node::T_INT) {
+									first->v_int--;
 									return first;
                                 }
                                 else {
-									first.v_double--;
+									first->v_double--;
 									return first;
                                 }
                             }
                         case node::FLOOR: { // (floor X)
-                            return node(floor(eval(n.v_list[1], env).to_double()));}
+                            return make_snode(floor(eval(n->v_list[1], env)->to_double()));}
                         case node::CEIL: { // (ceil X)
-                            return node(ceil(eval(n.v_list[1], env).to_double()));}
+                            return make_snode(ceil(eval(n->v_list[1], env)->to_double()));}
                         case node::LN: { // (ln X)
-                            return node(log(eval(n.v_list[1], env).to_double()));}
+                            return make_snode(log(eval(n->v_list[1], env)->to_double()));}
                         case node::LOG10: { // (log10 X)
-                            return node(log10(eval(n.v_list[1], env).to_double()));}
+                            return make_snode(log10(eval(n->v_list[1], env)->to_double()));}
                         case node::RAND: { // (rand)
-                            return node(rand_double());}
+                            return make_snode(rand_double());}
                         case node::SET: // (set SYMBOL VALUE)
                             {
-								node v = eval(n.v_list[2], env);
-								return env.set(n.v_list[1], v);
+								snode v = make_snode(*eval(n->v_list[2], env));
+								return env.set(n->v_list[1], v);
                             }
                         case node::EQEQ: { // (== X ..) short-circuit                    
-                            node first = eval(n.v_list[1], env);
-                            if (first.type == node::T_INT) {
-                                int firstv = first.v_int;
-                                for (vector<node>::iterator i = n.v_list.begin() + 2; i != n.v_list.end(); i++) {
-                                    if (eval(*i, env).to_int() != firstv) {return node(false);}
+                            snode first = eval(n->v_list[1], env);
+                            if (first->type == node::T_INT) {
+                                int firstv = first->v_int;
+                                for (vector<snode>::iterator i = n->v_list.begin() + 2; i != n->v_list.end(); i++) {
+                                    if (eval(*i, env)->to_int() != firstv) {return make_snode(false);}
                                 }
                             }
                             else {
-                                double firstv = first.v_double;
-                                for (vector<node>::iterator i = n.v_list.begin() + 2; i != n.v_list.end(); i++) {
-                                    if (eval(*i, env).to_double() != firstv) {return node(false);}
+                                double firstv = first->v_double;
+                                for (vector<snode>::iterator i = n->v_list.begin() + 2; i != n->v_list.end(); i++) {
+                                    if (eval(*i, env)->to_double() != firstv) {return make_snode(false);}
                                 }
                             }
-                            return node(true);}
+                            return node_true;}
                         case node::NOTEQ: { // (!= X ..) short-circuit                    
-                            node first = eval(n.v_list[1], env);
-                            if (first.type == node::T_INT) {
-                                int firstv = first.v_int;
-                                for (vector<node>::iterator i = n.v_list.begin() + 2; i != n.v_list.end(); i++) {
-                                    if (eval(*i, env).to_int() == firstv) {return node(false);}
+                            snode first = eval(n->v_list[1], env);
+                            if (first->type == node::T_INT) {
+                                int firstv = first->v_int;
+                                for (vector<snode>::iterator i = n->v_list.begin() + 2; i != n->v_list.end(); i++) {
+                                    if (eval(*i, env)->to_int() == firstv) {return make_snode(false);}
                                 }
                             }
                             else {
-                                double firstv = first.v_double;
-                                for (vector<node>::iterator i = n.v_list.begin() + 2; i != n.v_list.end(); i++) {
-                                    if (eval(*i, env).to_double() == firstv) {return node(false);}
+                                double firstv = first->v_double;
+                                for (vector<snode>::iterator i = n->v_list.begin() + 2; i != n->v_list.end(); i++) {
+                                    if (eval(*i, env)->to_double() == firstv) {return make_snode(false);}
                                 }
                             }
-                            return node(true);}
+                            return node_true;}
                         case node::LT: { // (< X Y)
-                            node first = eval(n.v_list[1], env);
-                            node second = eval(n.v_list[2], env);
-                            if (first.type == node::T_INT) {
-                                return node(first.v_int < second.to_int());
+                            snode first = eval(n->v_list[1], env);
+                            snode second = eval(n->v_list[2], env);
+                            if (first->type == node::T_INT) {
+                                return make_snode(first->v_int < second->to_int());
                             }
                             else {
-                                return node(first.v_double < second.to_double());
+                                return make_snode(first->v_double < second->to_double());
                             }}
                         case node::GT: { // (> X Y)
-                            node first = eval(n.v_list[1], env);
-                            node second = eval(n.v_list[2], env);
-                            if (first.type == node::T_INT) {
-                                return node(first.v_int > second.to_int());
+                            snode first = eval(n->v_list[1], env);
+                            snode second = eval(n->v_list[2], env);
+                            if (first->type == node::T_INT) {
+                                return make_snode(first->v_int > second->to_int());
                             }
                             else {
-                                return node(first.v_double > second.to_double());
+                                return make_snode(first->v_double > second->to_double());
                             }}
                         case node::LTE: { // (<= X Y)
-                            node first = eval(n.v_list[1], env);
-                            node second = eval(n.v_list[2], env);
-                            if (first.type == node::T_INT) {
-                                return node(first.v_int <= second.to_int());
+                            snode first = eval(n->v_list[1], env);
+                            snode second = eval(n->v_list[2], env);
+                            if (first->type == node::T_INT) {
+                                return make_snode(first->v_int <= second->to_int());
                             }
                             else {
-                                return node(first.v_double <= second.to_double());
+                                return make_snode(first->v_double <= second->to_double());
                             }}
                         case node::GTE: { // (>= X Y)
-                            node first = eval(n.v_list[1], env);
-                            node second = eval(n.v_list[2], env);
-                            if (first.type == node::T_INT) {
-                                return node(first.v_int >= second.to_int());
+                            snode first = eval(n->v_list[1], env);
+                            snode second = eval(n->v_list[2], env);
+                            if (first->type == node::T_INT) {
+                                return make_snode(first->v_int >= second->to_int());
                             }
                             else {
-                                return node(first.v_double >= second.to_double());
+                                return make_snode(first->v_double >= second->to_double());
                             }}
                         case node::ANDAND: { // (&& X ..) short-circuit
-                            for (vector<node>::iterator i = n.v_list.begin() + 1; i != n.v_list.end(); i++) {
-                                if (!eval(*i, env).v_bool) {return node(false);}
+                            for (vector<snode>::iterator i = n->v_list.begin() + 1; i != n->v_list.end(); i++) {
+                                if (!eval(*i, env)->v_bool) {return node_false;}
                             }
-                            return node(true);}
+                            return node_true;}
                         case node::OROR: { // (|| X ..) short-circuit
-                            for (vector<node>::iterator i = n.v_list.begin() + 1; i != n.v_list.end(); i++) {
-                                if (eval(*i, env).v_bool) {return node(true);}
+                            for (vector<snode>::iterator i = n->v_list.begin() + 1; i != n->v_list.end(); i++) {
+                                if (eval(*i, env)->v_bool) {return node_true;}
                             }
-                            return node(false);}
+                            return node_false;}
                         case node::NOT: { // (! X)
-                            return node(!(eval(n.v_list[1], env).v_bool));}
+                            return make_snode(!(eval(n->v_list[1], env)->v_bool));}
                         case node::IF: { // (if CONDITION THEN_EXPR ELSE_EXPR)
-                            node &cond = n.v_list[1];
-                            if (eval(cond, env).v_bool) {
-                                return eval(n.v_list[2], env);
+                            snode &cond = n->v_list[1];
+                            if (eval(cond, env)->v_bool) {
+                                return eval(n->v_list[2], env);
                             }
                             else {
-                                return eval(n.v_list[3], env);
+                                return eval(n->v_list[3], env);
                             }}
                         case node::WHEN: { // (when CONDITION EXPR ..)
-                            node &cond = n.v_list[1];
-                            if (eval(cond, env).v_bool) {
-                                int len = n.v_list.size();
+                            snode &cond = n->v_list[1];
+                            if (eval(cond, env)->v_bool) {
+                                int len = n->v_list.size();
                                 for (int i = 2; i < len - 1; i++) {
-                                    eval(n.v_list[i], env);
+                                    eval(n->v_list[i], env);
                                 }
-                                return eval(n.v_list[len - 1], env); // returns last EXPR
+                                return eval(n->v_list[len - 1], env); // returns last EXPR
                             }
                             return nil;}
                         case node::FOR: // (for SYMBOL START END STEP EXPR ..)
                             {
-                                node start = eval(n.v_list[2], env);
-                                //env.env[n.v_list[1].v_string] = start;
-								env.set(n.v_list[1], start);
-                                int len = n.v_list.size();
+                                node start = *eval(n->v_list[2], env);
+								snode sstart = make_snode(start);
+                                //env.env[n->v_list[1].v_string] = start;
+								env.set(n->v_list[1], sstart);
+                                int len = n->v_list.size();
                                 if (start.type == node::T_INT) {                            
-                                    int last = eval(n.v_list[3], env).to_int();
-                                    int step = eval(n.v_list[4], env).to_int();                                
-									int &a = env.get(n.v_list[1]).v_int;
+                                    int last = eval(n->v_list[3], env)->to_int();
+                                    int step = eval(n->v_list[4], env)->to_int();                                
+									int &a = env.get(n->v_list[1])->v_int;
                                     if (step >= 0) {
                                         for (; a <= last; a += step) {
                                             for (int i = 5; i < len; i++) {
-                                                eval(n.v_list[i], env);
+                                                eval(n->v_list[i], env);
                                             }
                                         }
                                     }
                                     else {
                                         for (; a >= last; a += step) {
                                             for (int i = 5; i < len; i++) {
-                                                eval(n.v_list[i], env);
+                                                eval(n->v_list[i], env);
                                             }
                                         }
                                     }
                                 }
                                 else {
-                                    double last = eval(n.v_list[3], env).to_double();
-                                    double step = eval(n.v_list[4], env).to_double();                                
-									double &a = env.get(n.v_list[1]).v_double;
+                                    double last = eval(n->v_list[3], env)->to_double();
+                                    double step = eval(n->v_list[4], env)->to_double();                                
+									double &a = env.get(n->v_list[1])->v_double;
                                     if (step >= 0) {
                                         for (; a <= last; a += step) {
                                             for (int i = 5; i < len; i++) {
-                                                eval(n.v_list[i], env);
+                                                eval(n->v_list[i], env);
                                             }
                                         }
                                     }
                                     else {
                                         for (; a >= last; a += step) {
                                             for (int i = 5; i < len; i++) {
-                                                eval(n.v_list[i], env);
+                                                eval(n->v_list[i], env);
                                             }
                                         }
                                     }
                                 return nil;
                             }
                         case node::WHILE: { // (while CONDITION EXPR ..)
-                            node &cond = n.v_list[1];
-                            int len = n.v_list.size();
-                            while (eval(cond, env).v_bool) {
+                            snode &cond = n->v_list[1];
+                            int len = n->v_list.size();
+                            while (eval(cond, env)->v_bool) {
                                 for (int i = 2; i < len; i++) {
-                                    eval(n.v_list[i], env);
+                                    eval(n->v_list[i], env);
                                 }
                             }
                             return nil; }
                         case node::STRLEN: { // (strlen X)
-                            return node((int) eval(n.v_list[1], env).v_string.size());}
+                            return make_snode((int) eval(n->v_list[1], env)->v_string.size());}
                         case node::STRCAT: { // (strcat X ..)
-                            int len = n.v_list.size();
-                            if (len <= 1) return node("");
-                            node first = eval(n.v_list[1], env);
-                            string acc = first.to_string();
-                            for (vector<node>::iterator i = n.v_list.begin() + 2; i != n.v_list.end(); i++) {
-                                acc += eval(*i, env).to_string();
+                            int len = n->v_list.size();
+                            if (len <= 1) return make_snode("");
+                            snode first = eval(n->v_list[1], env);
+                            string acc = first->to_string();
+                            for (vector<snode>::iterator i = n->v_list.begin() + 2; i != n->v_list.end(); i++) {
+                                acc += eval(*i, env)->to_string();
                             }
-                            return node(acc);}
+                            return make_snode(acc);}
                         case node::CHAR_AT: { // (char-at X)
-                            return node(eval(n.v_list[1], env).v_string[eval(n.v_list[2], env).to_int()]);}
+                            return make_snode(eval(n->v_list[1], env)->v_string[eval(n->v_list[2], env)->to_int()]);}
                         case node::CHR: { // (chr X)
                             char temp[2] = " ";
-                            temp[0] = (char) eval(n.v_list[1], env).to_int();
-                            return node(string(temp));}
+                            temp[0] = (char) eval(n->v_list[1], env)->to_int();
+                            return make_snode(string(temp));}
                         case node::STRING: { // (string X)
-                            return node(eval(n.v_list[1], env).to_string());}
+                            return make_snode(eval(n->v_list[1], env)->to_string());}
                         case node::DOUBLE: { // (double X)
-                            return node(eval(n.v_list[1], env).to_double());}
+                            return make_snode(eval(n->v_list[1], env)->to_double());}
                         case node::INT: { // (int X)
-                            return node(eval(n.v_list[1], env).to_int());}
+                            return make_snode(eval(n->v_list[1], env)->to_int());}
                         case node::READ_STRING: { // (read-string X)
-                            return node(parse(eval(n.v_list[1], env).to_string())[0]);}
+                            return parse(eval(n->v_list[1], env)->to_string())[0];}
                         case node::TYPE: { // (type X)
-                            return node(eval(n.v_list[1], env).type_str());}
+                            return make_snode(eval(n->v_list[1], env)->type_str());}
                         case node::EVAL: { // (eval X)                    
-                            node n2 = eval(n.v_list[1], env);
-                            return node(eval(n2, env));}
+                            snode n2 = eval(n->v_list[1], env);
+                            return eval(n2, env);}
                         case node::QUOTE: { // (quote X)
-                            return n.v_list[1];}
+                            return n->v_list[1];}
                         case node::FN: { // (fn (ARGUMENT ..) BODY) => lexical closure
-                            node n2 = fn(n.v_list, &env);
+                            snode n2 = fn(make_snode(n->v_list), &env);
                             return n2;}
                         case node::LIST: { // (list X ..)
-                            vector<node> ret;
-                            for (unsigned int i = 1; i < n.v_list.size(); i++) {
-                                ret.push_back(eval(n.v_list[i], env));
+                            vector<snode> ret;
+                            for (unsigned int i = 1; i < n->v_list.size(); i++) {
+                                ret.push_back(eval(n->v_list[i], env));
                             }
-                            return node(ret);}
+                            return make_snode(ret);}
                         case node::APPLY: { // (apply FUNC LIST)
-                            vector<node> expr;
-                            node f = eval(n.v_list[1], env);
+                            vector<snode> expr;
+                            snode f = eval(n->v_list[1], env);
                             expr.push_back(f);
-                            vector<node> lst = eval(n.v_list[2], env).v_list;
+                            vector<snode> lst = eval(n->v_list[2], env)->v_list;
                             for (unsigned int i = 0; i < lst.size(); i++) {
                                 expr.push_back(lst.at(i));
                             }
-                            node n2 = node(expr);
+                            snode n2 = make_snode(expr);
                             return eval(n2, env);
                         }
                         case node::FOLD: { // (fold FUNC LIST)
-                            node f = eval(n.v_list.at(1), env);
-                            vector<node> lst = eval(n.v_list.at(2), env).v_list;
-                            node acc = eval(lst.at(0), env);
-                            vector<node> expr; // (FUNC ITEM)
+                            snode f = eval(n->v_list.at(1), env);
+                            vector<snode> lst = eval(n->v_list.at(2), env)->v_list;
+                            snode acc = eval(lst.at(0), env);
+                            vector<snode> expr; // (FUNC ITEM)
                             expr.push_back(f);
-                            expr.push_back(node()); // first argument
-                            expr.push_back(node()); // second argument
+                            expr.push_back(nil); // first argument
+                            expr.push_back(nil); // second argument
                             for (unsigned int i = 1; i < lst.size(); i++) {
                                 expr[1] = acc;
                                 expr[2] = lst.at(i);
-                                node n2 = node(expr);
+                                snode n2 = make_snode(expr);
                                 acc = eval(n2, env);
                             }
                             return acc;
                         }
                         case node::MAP: { // (map FUNC LIST)
-                            node f = eval(n.v_list.at(1), env);
-                            vector<node> lst = eval(n.v_list.at(2), env).v_list;
-                            vector<node> acc;
-                            vector<node> expr; // (FUNC ITEM)
+                            snode f = eval(n->v_list.at(1), env);
+                            vector<snode> lst = eval(n->v_list.at(2), env)->v_list;
+                            vector<snode> acc;
+                            vector<snode> expr; // (FUNC ITEM)
                             expr.push_back(f);
-                            expr.push_back(node());
+                            expr.push_back(nil);
                             for (unsigned int i = 0; i < lst.size(); i++) {
                                 expr[1] = lst.at(i);
-                                node n2 = node(expr);
+                                snode n2 = make_snode(expr);
                                 acc.push_back(eval(n2, env));
                             }                    
-                            return node(acc);
+                            return make_snode(acc);
                         }
                         case node::FILTER: { // (filter FUNC LIST)
-                            node f = eval(n.v_list.at(1), env);
-                            vector<node> lst = eval(n.v_list.at(2), env).v_list;
-                            vector<node> acc;
-                            vector<node> expr; // (FUNC ITEM)
+                            snode f = eval(n->v_list.at(1), env);
+                            vector<snode> lst = eval(n->v_list.at(2), env)->v_list;
+                            vector<snode> acc;
+                            vector<snode> expr; // (FUNC ITEM)
                             expr.push_back(f);
-                            expr.push_back(node());
+                            expr.push_back(nil);
                             for (unsigned int i = 0; i < lst.size(); i++) {
-                                node item = lst.at(i);
+                                snode item = lst.at(i);
                                 expr[1] = item;
-                                node n2 = node(expr);
-                                node ret = eval(n2, env);
-                                if (ret.v_bool) acc.push_back(item);
+                                snode n2 = make_snode(expr);
+                                snode ret = eval(n2, env);
+                                if (ret->v_bool) acc.push_back(item);
                             }                    
-                            return node(acc);
+                            return make_snode(acc);
                         }
                         case node::RANGE: { // (range START END STEP)
-                            node start = eval(n.v_list.at(1), env);                    
-                            vector<node> ret;
+                            node start = *eval(n->v_list.at(1), env);                    
+                            vector<snode> ret;
                             if (start.type == node::T_INT) {
-                                int a = eval(n.v_list.at(1), env).to_int();
-                                int last = eval(n.v_list.at(2), env).to_int();
-                                int step = eval(n.v_list.at(3), env).to_int();
+                                int a = eval(n->v_list.at(1), env)->to_int();
+                                int last = eval(n->v_list.at(2), env)->to_int();
+                                int step = eval(n->v_list.at(3), env)->to_int();
                                 if (step >= 0) {
                                     for (; a <= last; a += step) {
-                                        ret.push_back(node(a));}}
+                                        ret.push_back(make_snode(a));}}
                                 else {
                                     for (; a >= last; a += step) {
-                                        ret.push_back(node(a));}}
+                                        ret.push_back(make_snode(a));}}
                             }
                             else {
-                                double a = eval(n.v_list.at(1), env).to_double();
-                                double last = eval(n.v_list.at(2), env).to_double();
-                                double step = eval(n.v_list.at(3), env).to_double();
+                                double a = eval(n->v_list.at(1), env)->to_double();
+                                double last = eval(n->v_list.at(2), env)->to_double();
+                                double step = eval(n->v_list.at(3), env)->to_double();
                                 if (step >= 0) {
                                     for (; a <= last; a += step) {
-                                        ret.push_back(node(a));}}
+                                        ret.push_back(make_snode(a));}}
                                 else {
                                     for (; a >= last; a += step) {
-                                        ret.push_back(node(a));}}
+                                        ret.push_back(make_snode(a));}}
                             }
-                            return node(ret);
+                            return make_snode(ret);
                         }
                         case node::NTH: { // (nth INDEX LIST)
-                            int i = eval(n.v_list.at(1), env).to_int();
-                            const vector<node> &lst = eval(n.v_list.at(2), env).v_list;
+                            int i = eval(n->v_list.at(1), env)->to_int();
+                            vector<snode> &lst = eval(n->v_list.at(2), env)->v_list;
                             return lst.at(i);}
                         case node::LENGTH: { // (length LIST)                    
-                            const vector<node> &lst = eval(n.v_list.at(1), env).v_list;
-                            return node((int) lst.size());}
+                            const vector<snode> &lst = eval(n->v_list.at(1), env)->v_list;
+                            return make_snode((int) lst.size());}
                         case node::BEGIN: { // (begin X ..)                    
-                            int last = n.v_list.size() - 1;
+                            int last = n->v_list.size() - 1;
                             if (last <= 0) return nil;
                             for (int i = 1; i < last; i++) {
-                                eval(n.v_list[i], env);
+                                eval(n->v_list[i], env);
                             }
-                            return eval(n.v_list[last], env);}
+                            return eval(n->v_list[last], env);}
                         case node::PR: // (pr X ..)
                             {
-                                vector<node>::iterator first = n.v_list.begin() + 1;
-                                for (vector<node>::iterator i = first; i != n.v_list.end(); i++) {
+                                vector<snode>::iterator first = n->v_list.begin() + 1;
+                                for (vector<snode>::iterator i = first; i != n->v_list.end(); i++) {
                                     if (i != first) printf(" ");
-                                    printf("%s", eval(*i, env).to_string().c_str());
+                                    printf("%s", eval(*i, env)->to_string().c_str());
                                 }
                                 return nil;
                             }
                         case node::PRN: // (prn X ..)
                             {
-                                vector<node>::iterator first = n.v_list.begin() + 1;
-                                for (vector<node>::iterator i = first; i != n.v_list.end(); i++) {
+                                vector<snode>::iterator first = n->v_list.begin() + 1;
+                                for (vector<snode>::iterator i = first; i != n->v_list.end(); i++) {
                                     if (i != first) printf(" ");
-                                    printf("%s", eval(*i, env).to_string().c_str());
+                                    printf("%s", eval(*i, env)->to_string().c_str());
                                 }
                                 puts("");
                                 return nil;
                             }
                         case node::EXIT: { // (exit X)
                                 puts("");
-                                exit(eval(n.v_list[1], env).to_int());
+                                exit(eval(n->v_list[1], env)->to_int());
                                 return nil; }
                         case node::SYSTEM: { // Invokes the command processor to execute a command.
                             string cmd;
-                            for (unsigned int i = 1; i < n.v_list.size(); i++) {
+                            for (unsigned int i = 1; i < n->v_list.size(); i++) {
                                 if (i != 1) cmd += ' ';
-                                cmd += eval(n.v_list[i], env).v_string;
+                                cmd += eval(n->v_list[i], env)->v_string;
                             }
-                            return node(system(cmd.c_str()));}
+                            return make_snode(system(cmd.c_str()));}
                         case node::CONS: { // (cons x lst): Returns a new list where x is the first element and lst is the rest.
-                            node x = eval(n.v_list[1], env);
-                            vector<node> lst = eval(n.v_list[2], env).v_list;
-                            vector<node> r;
+                            snode x = eval(n->v_list[1], env);
+                            vector<snode> lst = eval(n->v_list[2], env)->v_list;
+                            vector<snode> r;
                             r.push_back(x);
-                            for (vector<node>::iterator i = lst.begin(); i != lst.end(); i++) {
+                            for (vector<snode>::iterator i = lst.begin(); i != lst.end(); i++) {
                                 r.push_back(*i);
                             }
-                            return r;
+                            return make_snode(r);
                         }
 						case node::READ_LINE: { // (read-line)
 							string line;
 							if (!getline(cin, line)) { // EOF								
 								return nil;
 							} else {
-								return node(line);
+								return make_snode(line);
 							}
 						}
 						case node::SLURP: { // (slurp FILENAME)
-							string filename = eval(n.v_list[1], env).v_string;
+							string filename = eval(n->v_list[1], env)->v_string;
 							string str;
 							if (slurp(filename, str))
-								return node(str);
+								return make_snode(str);
 							else
 								return nil;
 						}
 						case node::SPIT: { // (spit FILENAME STRING)
-							string filename = eval(n.v_list[1], env).v_string;
-							string str = eval(n.v_list[2], env).v_string;
-							return node(spit(filename, str));
+							string filename = eval(n->v_list[1], env)->v_string;
+							string str = eval(n->v_list[2], env)->v_string;
+							return make_snode(spit(filename, str));
 						}
                         default: {
                             cerr << "Not implemented function: [" << func.v_string << "]" << endl;
                     } // end switch
                 }
                 else {
-                    vector<node> &f = func.v_list;
+                    vector<snode> &f = func.v_list;
                     if (func.type == node::T_FN) {
-                        // anonymous function application. lexical scoping
+                        // anonymous function application-> lexical scoping
                         // (fn (ARGUMENT ..) BODY ..)
-                        vector<node> &arg_syms = f[1].v_list;
+                        vector<snode> &arg_syms = f[1]->v_list;
 
 						environment local_env(func.outer_env);
                         int alen = arg_syms.size();
                         for (int i=0; i<alen; i++) { // assign arguments
-                            //string &k = arg_syms.at(i).v_string;
-							//local_env.env[k] = eval(n.v_list.at(i+1), env);
-							node &k = arg_syms[i];
-							local_env.env[k.code] = eval(n.v_list.at(i+1), env);
+                            //string &k = arg_syms.at(i)->v_string;
+							//local_env.env[k] = eval(n->v_list.at(i+1), env);
+							snode &k = arg_syms[i];
+							local_env.env[k->code] = eval(n->v_list.at(i+1), env);
                         }
 
                         int flen = f.size();
                         for (int i=2; i<flen-1; i++) { // body
                             eval(f.at(i), local_env);
                         }
-                        node ret = eval(f.at(flen-1), local_env);
+                        snode ret = eval(f.at(flen-1), local_env);
                         return ret;
                     }
                     else {
         }
     }
 
-    vector<node> paren::compile_all(vector<node> &lst) {
-        vector<node> compiled;
+    vector<snode> paren::compile_all(vector<snode> &lst) {
+        vector<snode> compiled;
         int last = lst.size() - 1;        
         for (int i = 0; i <= last; i++) {
             compiled.push_back(compile(lst[i]));
         return compiled;
     }
 
-    node paren::eval_all(vector<node> &lst) {
+    snode paren::eval_all(vector<snode> &lst) {
         int last = lst.size() - 1;
         if (last < 0) return nil;
         for (int i = 0; i < last; i++) {
         puts("Predefined Symbols:");
         //print_map_keys(global_env.env);
 		vector<string> v;
-		for (map<int, node>::iterator iter = global_env.env.begin(); iter != global_env.env.end(); iter++) {			
+		for (map<int, snode>::iterator iter = global_env.env.begin(); iter != global_env.env.end(); iter++) {			
 			v.push_back(symname[iter->first]);
 		}
 		sort(v.begin(), v.end());
 
     inline void paren::init() {
         srand((unsigned int) time(0));
-        global_env.env[ToCode("true")] = node(true);
-        global_env.env[ToCode("false")] = node(false);
-        global_env.env[ToCode("E")] = node(2.71828182845904523536);
-        global_env.env[ToCode("PI")] = node(3.14159265358979323846);
+        global_env.env[ToCode("true")] = make_snode(true);
+        global_env.env[ToCode("false")] = make_snode(false);
+        global_env.env[ToCode("E")] = make_snode(2.71828182845904523536);
+        global_env.env[ToCode("PI")] = make_snode(3.14159265358979323846);
                 
         global_env.env[ToCode("+")] = builtin(node::PLUS);
         global_env.env[ToCode("-")] = builtin(node::MINUS);
 		eval_string("(defmacro defn (...) (setfn ...))");
     }
 
-    node paren::eval_string(string &s) {
-        vector<node> vec = parse(s);
-		vector<node> compiled = compile_all(vec);
+    snode paren::eval_string(string &s) {
+        vector<snode> vec = parse(s);
+		vector<snode> compiled = compile_all(vec);
         return eval_all(compiled);
     }
 
-    node paren::eval_string(const char* s) {
+    snode paren::eval_string(const char* s) {
         string s2(s);
         return eval_string(s2);
     }
 
     inline void paren::eval_print(string &s) {
-		puts(eval_string(s).str_with_type().c_str());
+		puts(eval_string(s)->str_with_type().c_str());
     }
 
     // read-eval-print loop
         }
     }
 
-    node &paren::get(const char* name) {
+    snode paren::get(const char* name) {
         string s(name);
         return global_env.get(ToCode(s));
     }
 
-    void paren::set(const char* name, node value) {
+    void paren::set(const char* name, snode &value) {
         string s(name);
         global_env.env[ToCode(s)] = value;
     }
 #include <cmath>
 #include <map>
 #include <ctime>
+#include <memory>
 
-#define PAREN_VERSION "1.5.14"
+#define PAREN_VERSION "1.6"
 
 namespace libparen {
     using namespace std;
 
+	struct node;
 	struct environment;
+	typedef shared_ptr<node> snode;
 
     struct node {
         enum {T_NIL, T_INT, T_DOUBLE, T_BOOL, T_STRING, T_SYMBOL, T_LIST, T_BUILTIN, T_FN} type;
             int v_int;
             double v_double;
             bool v_bool;
-			node *p_node; // if T_SYMBOL, cached address of the data
+			//node *p_node; // if T_SYMBOL, cached address of the data
 			environment *outer_env; // if T_FN
         };
         string v_string;
-        vector<node> v_list;
-		int code; // if T_SYMBOL, code for faster access
+        vector<snode> v_list;
+		int code; // if T_SYMBOL, code for faster access		
 
         node();
         node(int a);
         node(double a);
-        node(bool a);        
+        node(bool a);
         node(const string &a);
-        node(const vector<node> &a);
+        node(const vector<snode> &a);
 
         int to_int(); // convert to int
         double to_double(); // convert to double
     };
 
     struct environment {
-        map<int, node> env;
+        map<int, snode> env;
         environment *outer;
         environment();
         environment(environment *outer);
-        node &get(int code);
-		node &get(node &k);
-		node &set(node &k, node &v);
+        snode get(int code);
+		snode get(snode &k);
+		snode set(snode &k, snode &v);
     };
 
     struct paren {
 
         inline double rand_double();
         vector<string> tokenize(const string &s);
-        vector<node> parse(const string &s);
+        vector<snode> parse(const string &s);
 
         environment global_env; // variables
                 
-        node eval(node &n, environment &env);        
-        node eval_all(vector<node> &lst);
-        node compile(node &n);
-        vector<node> compile_all(vector<node> &lst);
+        snode eval(snode &n, environment &env);        
+        snode eval_all(vector<snode> &lst);
+        snode compile(snode &n);
+        vector<snode> compile_all(vector<snode> &lst);
         void print_logo();
         void prompt();
         void prompt2();
         inline void init();
-        node eval_string(string &s);
-        node eval_string(const char* s);
+        snode eval_string(string &s);
+        snode eval_string(const char* s);
         inline void eval_print(string &s);
         void repl(); // read-eval-print loop
 
-        node &get(const char* name);
-        void set(const char* name, node value);
+        snode get(const char* name);
+        void set(const char* name, snode &value);
     }; // struct paren
 
 	bool slurp(string filename, string &str);
       <Optimization>Full</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
     </ClCompile>
     <Link>