return newenv;
 }
+
+
+char* lookup_builtin(Sexpr* b) {
+       // uh yeah i guess
+       // needs to be updated manually i suppose
+       uint64_t prefix = b->value.b.opcode >> 8;
+       uint64_t suffix = b->value.b.opcode & 0xff;
+       switch(prefix) {
+       case CORE_PREFIX:
+               switch(suffix) {
+               case CORE_QUOTE:
+                       return CORE_QUOTE_STR;
+               case CORE_CONS:
+                       return CORE_CONS_STR;
+               case CORE_CAR:
+                       return CORE_CAR_STR;
+               case CORE_CDR:
+                       return CORE_CDR_STR;
+               case CORE_IF:
+                       return CORE_IF_STR;
+               case CORE_EQ:
+                       return CORE_EQ_STR;
+               case CORE_NOT:
+                       return CORE_NOT_STR;
+               case CORE_ATOM:
+                       return CORE_ATOM_STR;
+               case CORE_DEF:
+                       return CORE_DEF_STR;
+               case CORE_EXIT:
+                       return CORE_EXIT_STR;
+               default:
+                       return "NOT FOUND (CORE)";
+               }
+       case ARITH_PREFIX:
+               switch(suffix) {
+               case ARITH_ADD:
+                       return ARITH_ADD_STR;
+               case ARITH_SUB:
+                       return ARITH_SUB_STR;
+               case ARITH_MUL:
+                       return ARITH_MUL_STR;
+               case ARITH_DIV:
+                       return ARITH_DIV_STR;
+               case ARITH_MOD:
+                       return ARITH_MOD_STR;
+               default:
+                       return "NOT FOUND (ARITH)";
+               }
+       case COMB_PREFIX:
+               switch(suffix) {
+               case COMB_I:
+                       return COMB_I_STR;
+               case COMB_S:
+                       return COMB_S_STR;
+               case COMB_K:
+                       return COMB_K_STR;
+               case COMB_B:
+                       return COMB_B_STR;
+               case COMB_C:
+                       return COMB_C_STR;
+               case COMB_W:
+                       return COMB_W_STR;
+               case COMB_PHI:
+                       return COMB_PHI_STR;
+               case COMB_PSI:
+                       return COMB_PSI_STR;
+               case COMB_Z:
+                       return COMB_Z_STR;
+               default:
+                       return "NOT FOUND (COMB)";
+               }
+       case IO_PREFIX:
+               switch(suffix) {
+               case IO_PRINT:
+                       return IO_PRINT_STR;
+               case IO_BPA:
+                       return IO_BPA_STR;
+               default:
+                       return "NOT FOUND (IO)";
+               }
+       default:
+               return "NOT FOUND";
+       }
+       return "NOT FOUND";
+}
+
 
 void load_builtin(char* ks, uint64_t op, Sexpr* env);
 Sexpr* load_env(Sexpr* env);
 
+char* lookup_builtin(Sexpr* b);
+
 #endif
 
 }
 
 Sexpr* load_arith_env(Sexpr* env) {
-       load_builtin("+", (ARITH_PREFIX << 8) | ARITH_ADD, env);
-       load_builtin("-", (ARITH_PREFIX << 8) | ARITH_SUB, env);
-       load_builtin("*", (ARITH_PREFIX << 8) | ARITH_MUL, env);
-       load_builtin("/", (ARITH_PREFIX << 8) | ARITH_DIV, env);
-       load_builtin("%", (ARITH_PREFIX << 8) | ARITH_MOD, env);
+       load_builtin(ARITH_ADD_STR, (ARITH_PREFIX << 8) | ARITH_ADD, env);
+       load_builtin(ARITH_SUB_STR, (ARITH_PREFIX << 8) | ARITH_SUB, env);
+       load_builtin(ARITH_MUL_STR, (ARITH_PREFIX << 8) | ARITH_MUL, env);
+       load_builtin(ARITH_DIV_STR, (ARITH_PREFIX << 8) | ARITH_DIV, env);
+       load_builtin(ARITH_MOD_STR, (ARITH_PREFIX << 8) | ARITH_MOD, env);
        
        return env;
 }
 
 
 #define ARITH_ADD 0x00
 #define ARITH_ADD_ARGS 2
+#define ARITH_ADD_STR "+"
 #define ARITH_SUB 0x01
 #define ARITH_SUB_ARGS 2
+#define ARITH_SUB_STR "-"
 #define ARITH_MUL 0x02
 #define ARITH_MUL_ARGS 2
+#define ARITH_MUL_STR "*"
 #define ARITH_DIV 0x03
 #define ARITH_DIV_ARGS 2
+#define ARITH_DIV_STR "/"
 #define ARITH_MOD 0x04
 #define ARITH_MOD_ARGS 2
+#define ARITH_MOD_STR "%"
 
 Sexpr* x_arith_dispatch(Sexpr* s, Sexpr* rest, Sexpr* env);
 Sexpr* load_arith_env(Sexpr* env);
 
        Sexpr* z = from_opcode((COMB_PREFIX << 8) | COMB_Z);
        Sexpr* zg = cons(z, cons(g2, from_nil()));
        //return cons(g, rest);
-       return cons(g,cons(zg, cons(v, rest)));
+       Sexpr* toret = cons(g,cons(zg, cons(v, rest)));
+       return toret;
 }
 
 
 }
 
 Sexpr* load_comb_env(Sexpr* env) {
-       load_builtin("I", (COMB_PREFIX << 8) | COMB_I, env);
-       load_builtin("S", (COMB_PREFIX << 8) | COMB_S, env);
-       load_builtin("K", (COMB_PREFIX << 8) | COMB_K, env);
-       load_builtin("B", (COMB_PREFIX << 8) | COMB_B, env);
-       load_builtin("C", (COMB_PREFIX << 8) | COMB_C, env);
-       load_builtin("W", (COMB_PREFIX << 8) | COMB_W, env);
-       load_builtin("Phi", (COMB_PREFIX << 8) | COMB_PHI, env);
-       load_builtin("Psi", (COMB_PREFIX << 8) | COMB_PSI, env);
-       load_builtin("Z", (COMB_PREFIX << 8) | COMB_Z, env);
+       load_builtin(COMB_I_STR, (COMB_PREFIX << 8) | COMB_I, env);
+       load_builtin(COMB_S_STR, (COMB_PREFIX << 8) | COMB_S, env);
+       load_builtin(COMB_K_STR, (COMB_PREFIX << 8) | COMB_K, env);
+       load_builtin(COMB_B_STR, (COMB_PREFIX << 8) | COMB_B, env);
+       load_builtin(COMB_C_STR, (COMB_PREFIX << 8) | COMB_C, env);
+       load_builtin(COMB_W_STR, (COMB_PREFIX << 8) | COMB_W, env);
+       load_builtin(COMB_PHI_STR, (COMB_PREFIX << 8) | COMB_PHI, env);
+       load_builtin(COMB_PSI_STR, (COMB_PREFIX << 8) | COMB_PSI, env);
+       load_builtin(COMB_Z_STR, (COMB_PREFIX << 8) | COMB_Z, env);
        
        return env;
 }
 
 
 #define COMB_I 0x00
 #define COMB_I_ARGS 1
+#define COMB_I_STR "I"
 #define COMB_S 0x01
 #define COMB_S_ARGS 3
+#define COMB_S_STR "S"
 #define COMB_K 0x02
 #define COMB_K_ARGS 2
+#define COMB_K_STR "K"
 #define COMB_B 0x03
 #define COMB_B_ARGS 3
+#define COMB_B_STR "B"
 #define COMB_C 0x04
 #define COMB_C_ARGS 3
+#define COMB_C_STR "C"
 #define COMB_W 0x05
 #define COMB_W_ARGS 2
+#define COMB_W_STR "W"
 #define COMB_PHI 0x06
 #define COMB_PHI_ARGS 4
+#define COMB_PHI_STR "Phi"
 #define COMB_PSI 0x07
 #define COMB_PSI_ARGS 4
+#define COMB_PSI_STR "Psi"
 #define COMB_Z 0x08
 #define COMB_Z_ARGS 2
+#define COMB_Z_STR "Z"
 
 Sexpr* x_comb_dispatch(Sexpr* s, Sexpr* rest, Sexpr* env);
 Sexpr* load_comb_env(Sexpr* env);
 
 
 
 Sexpr* load_core_env(Sexpr* env) {
-       load_builtin("quote", (CORE_PREFIX << 8) | CORE_QUOTE, env);
-       load_builtin("cons", (CORE_PREFIX << 8) | CORE_CONS, env);
-       load_builtin("car", (CORE_PREFIX << 8) | CORE_CAR, env);
-       load_builtin("cdr", (CORE_PREFIX << 8) | CORE_CDR, env);
-       load_builtin("if", (CORE_PREFIX << 8) | CORE_IF, env);
-       load_builtin("eq", (CORE_PREFIX << 8) | CORE_EQ, env);
-       load_builtin("not", (CORE_PREFIX << 8) | CORE_NOT, env);
-       load_builtin("atom", (CORE_PREFIX << 8) | CORE_ATOM, env);
+       load_builtin(CORE_QUOTE_STR, (CORE_PREFIX << 8) | CORE_QUOTE, env);
+       load_builtin(CORE_CONS_STR, (CORE_PREFIX << 8) | CORE_CONS, env);
+       load_builtin(CORE_CAR_STR, (CORE_PREFIX << 8) | CORE_CAR, env);
+       load_builtin(CORE_CDR_STR, (CORE_PREFIX << 8) | CORE_CDR, env);
+       load_builtin(CORE_IF_STR, (CORE_PREFIX << 8) | CORE_IF, env);
+       load_builtin(CORE_EQ_STR, (CORE_PREFIX << 8) | CORE_EQ, env);
+       load_builtin(CORE_NOT_STR, (CORE_PREFIX << 8) | CORE_NOT, env);
+       load_builtin(CORE_ATOM_STR, (CORE_PREFIX << 8) | CORE_ATOM, env);
        
-       load_builtin("def", (CORE_PREFIX << 8) | CORE_DEF, env);
-       load_builtin("exit", (CORE_PREFIX << 8) | CORE_EXIT, env);
+       load_builtin(CORE_DEF_STR, (CORE_PREFIX << 8) | CORE_DEF, env);
+       load_builtin(CORE_EXIT_STR, (CORE_PREFIX << 8) | CORE_EXIT, env);
        
        return env;
 }
 
 
 #define CORE_QUOTE 0x00
 #define CORE_QUOTE_ARGS 1
+#define CORE_QUOTE_STR "quote"
 #define CORE_CONS 0x01
 #define CORE_CONS_ARGS 2
+#define CORE_CONS_STR "cons"
 #define CORE_CAR 0x02
 #define CORE_CAR_ARGS 1
+#define CORE_CAR_STR "car"
 #define CORE_CDR 0x03
 #define CORE_CDR_ARGS 1
+#define CORE_CDR_STR "cdr"
 #define CORE_IF 0x04
 #define CORE_IF_ARGS 3
+#define CORE_IF_STR "if"
 #define CORE_EQ 0x05
 #define CORE_EQ_ARGS 2
+#define CORE_EQ_STR "eq"
 #define CORE_NOT 0x06
 #define CORE_NOT_ARGS 1
+#define CORE_NOT_STR "not"
 #define CORE_ATOM 0x07
 #define CORE_ATOM_ARGS 1
+#define CORE_ATOM_STR "atom"
 
 #define CORE_APPLYN 0x08
 #define CORE_APPLYN_ARGS 3
+#define CORE_APPLYN_STR "applyn"
 
 #define CORE_DEF 0xfe // huh do i want this so close to exit?
 #define CORE_DEF_ARGS 2
+#define CORE_DEF_STR "def"
 #define CORE_EXIT 0xff
 #define CORE_EXIT_ARGS 1
+#define CORE_EXIT_STR "exit"
 
 Sexpr* x_core_dispatch(Sexpr* s, Sexpr* rest, Sexpr* env);
 Sexpr* load_core_env(Sexpr* env);
 
 #include "../sexpr.h"
 #include "../config.h"
 #include "io.h"
+#include "../eval.h"
 
 #include <stdlib.h>
 #include <inttypes.h>
        return cons(from_t(), rest);
 }
 
+Sexpr* io_print_b(Sexpr* b, Sexpr* rest, Sexpr* env) {
+       if(IO_PB_ARGS != u64_get_num_args(b)) {
+               return cons(b, rest);
+       }
+       Sexpr* arg = clone(car(b->value.b.args));
+       sexpr_free(b);
+       Sexpr* argeval = eval(arg, env);
+       char* out = sprint_sexpr_builtin(argeval);
+       sexpr_free(argeval);
+       // uhh do i free arg? don't think so...
+       PRINT(out);
+       free(out);
+       return cons(from_t(), rest);
+}
+
 
 Sexpr* x_io_dispatch(Sexpr* b, Sexpr* rest, Sexpr* env) {
        uint64_t code = b->value.b.opcode & 0xff;
        switch(code) {
        case IO_PRINT:
                return io_print(b, rest, env);
+       case IO_PB:
+               return io_print_b(b, rest, env);
        default:
                return from_nil();
        }
 }
 
 Sexpr* load_io_env(Sexpr* env) {
-       load_builtin("print", (IO_PREFIX << 8) | IO_PRINT, env);
+       load_builtin(IO_PRINT_STR, (IO_PREFIX << 8) | IO_PRINT, env);
+       load_builtin(IO_PB_STR, (IO_PREFIX << 8) | IO_PB, env);
 
        return env;
 }
 
 
 #define IO_PRINT 0x00
 #define IO_PRINT_ARGS 1
+#define IO_PRINT_STR "print"
+#define IO_PB 0x01
+#define IO_PB_ARGS 1
+#define IO_PB_STR "pb"
 
 Sexpr* x_io_dispatch(Sexpr* s, Sexpr* rest, Sexpr* env);
 Sexpr* load_io_env(Sexpr* env);
 
 Sexpr* apply_builtin(Sexpr* func, Sexpr* arg, Sexpr* env);
 
 Sexpr* eval(Sexpr* s, Sexpr* dict) {
-       /* char* out = sprint_sexpr(s);
-       printf("s: %s\n", out);
+       /* char* out = sprint_sexpr_builtin(s);
+       PRINT(out);
        free(out); */
        // okay.. important to note,
        // this needs to free s
 
 
 #include "types.h"
 #include "sexpr.h"
+#include "builtins.h"
 
 
 Sexpr* from_nil() {
                out = malloc(nbytes*sizeof(char));
                out[0] = '_';
                snprintf(out + 1, nbytes, "%" PRIu64 "", s->value.b.opcode);
-               return out;             
+               return out;
        }
        else if(s->type == QUOTE) {
                return sprint_sexpr(s->value.q);
        }
        return NULL;
 }
+
+char* sprint_sexpr_builtin(Sexpr* s) {
+       if(s == NULL) {
+               WARN("UH OH IT'S NULL", "");
+               return NULL;
+       }
+       // assumes not null
+       size_t nbytes;
+       char* out;
+       if(s->type == NIL) {
+               out = malloc(4*sizeof(char));
+               strcpy(out, "nil");
+               return out;
+       }
+       else if(s->type == T) {
+               out = malloc(2*sizeof(char));
+               strcpy(out, "t");
+               return out;
+       }
+       else if(s->type == SYM) {
+               out = malloc(sizeof(char)*(strlen(s->value.s)+1));
+               strcpy(out, s->value.s);
+               return out;
+       }
+       else if(s->type == PTR) {
+               out = strdup("<*>");
+               return out;
+       }
+       else if(s->type == UINT) {
+               nbytes = snprintf(NULL, 0, "%" K_UINT_PRINT "", s->value.u) + 1;
+               out = malloc(nbytes*sizeof(char));
+               snprintf(out, nbytes, "%" PRIu64 "", s->value.u);
+               return out;
+       }
+       else if(s->type == BUILTIN) {
+               nbytes = snprintf(NULL, 0, "%s", lookup_builtin(s))+2;
+               //nbytes = snprintf(NULL, 0, "%" PRIu64 "", s->value.b.opcode) + 2;
+               out = malloc(nbytes*sizeof(char));
+               out[0] = '_';
+               snprintf(out  + 1, nbytes, "%s", lookup_builtin(s));
+               //snprintf(out  + 1, nbytes, "%" PRIu64 "", s->value.b.opcode);
+               out[nbytes-1] = '<';
+               //out[nbytes] = '\0';
+               char* rest = sprint_sexpr_builtin(s->value.b.args);
+               out = realloc(out, nbytes + strlen(rest) + 2);
+               strcpy(out+nbytes, rest);
+               out[nbytes+strlen(rest)] = '>';
+               out[nbytes+strlen(rest)+1] = '\0';
+               free(rest);
+               return out;
+       }
+       else if(s->type == QUOTE) {
+               return sprint_sexpr_builtin(s->value.q);
+       }
+       else if(s->type == CONS) {
+               Sexpr* curr_cell = s;
+               size_t currsize = 2;
+               out = malloc(currsize*sizeof(char));
+               out[0] = '(';
+               out[1] = '\0';
+               while(curr_cell->type == CONS) {
+                       char* carstr = sprint_sexpr_builtin(car(curr_cell));
+                       currsize += strlen(carstr) + 1; // trailing space/close paren
+                       out = realloc(out, currsize);
+                       strcat(out, carstr);
+                       free(carstr);
+                       strcat(out, " ");
+                       curr_cell = cdr(curr_cell);
+               }
+               if(curr_cell->type == NIL) {
+                       out[currsize-2] = ')';
+                       out[currsize-1] = '\0';
+                       return out;
+               }
+               else { // non-nil
+                       char* cdrstr = sprint_sexpr_builtin(curr_cell);
+                       currsize += strlen(cdrstr) + 4; // dot, space, close, null-terminator
+                       strcat(out, ". ");
+                       strcat(out, cdrstr);
+                       strcat(out, ")");
+                       out[currsize-1] = '\0';
+                       free(cdrstr);
+                       return out;
+               }
+       }
+       return NULL;
+}
 
 Sexpr* reverse(Sexpr* s);
 Sexpr* equal(Sexpr* a, Sexpr* b);
 char* sprint_sexpr(Sexpr* s);
+char* sprint_sexpr_builtin(Sexpr* s);
 
 #endif