#include <stdio.h>
 
-Sexpr* c_quote(Sexpr* b, Sexpr* env) {
+Sexpr* c_quote(Sexpr* b, Sexpr* rest, Sexpr* env) {
        if(CORE_QUOTE_ARGS != u64_get_num_args(b))
-               return b;
+               return cons(b, rest);
        //return car(b->value.b.args);
-       return from_quote(car(b->value.b.args));
+       return cons(from_quote(car(b->value.b.args)), rest);
 }
 
 // redo the rest of these...
-Sexpr* c_cons(Sexpr* b, Sexpr* env) {
+Sexpr* c_cons(Sexpr* b, Sexpr* rest, Sexpr* env) {
        if(CORE_CONS_ARGS != u64_get_num_args(b))
-               return b;
+               return cons(b, rest);
        Sexpr* args = b->value.b.args;
        Sexpr* _cdr = eval(car(args), env);
        Sexpr* _car = eval(car(cdr(args)), env);
-       return cons(_car, _cdr);
+       return cons(cons(_car, _cdr), rest);
 }
-Sexpr* c_car(Sexpr* b, Sexpr* env) {
+Sexpr* c_car(Sexpr* b, Sexpr* rest, Sexpr* env) {
        if(CORE_CAR_ARGS != u64_get_num_args(b))
-               return b;
+               return cons(b, rest);
        Sexpr* args = b->value.b.args;
-       return car(eval(car(args), env));
+       // huh okay, can i ditch the eval now that i'm doing the 'rest' thing?
+       return cons(car(eval(car(args), env)), rest);
 }
-Sexpr* c_cdr(Sexpr* b, Sexpr* env) {
+Sexpr* c_cdr(Sexpr* b, Sexpr* rest, Sexpr* env) {
        if(CORE_CDR_ARGS != u64_get_num_args(b))
-               return b;
+               return cons(b, rest);
        Sexpr* args = b->value.b.args;
-       return cdr(eval(car(args), env));
+       // see above
+       return cons(cdr(eval(car(args), env)), rest);
 }
-Sexpr* c_if(Sexpr* b, Sexpr* env) {
+Sexpr* c_if(Sexpr* b, Sexpr* rest, Sexpr* env) {
        if(CORE_IF_ARGS != u64_get_num_args(b))
-               return b;
+               return cons(b, rest);
        Sexpr* args = b->value.b.args;
        
        Sexpr* falsy = car(args);
        Sexpr* truthy = car(cdr(args));
        Sexpr* cond = car(cdr(cdr(args)));
        if(eval(cond, env)->type != NIL)
-               return truthy;
+               return cons(truthy, rest);
        else
-               return falsy;
-       // uhhh am I sure about this one?
-       // the lack of evals is perhaps a little suspect...
+               return cons(falsy, rest);
 }
-Sexpr* c_eq(Sexpr* b, Sexpr* env) {
+Sexpr* c_eq(Sexpr* b, Sexpr* rest, Sexpr* env) {
        if(CORE_EQ_ARGS != u64_get_num_args(b))
-               return b;
+               return cons(b, rest);
        Sexpr* args = b->value.b.args;
        // yeah eval is kinda necessary for this one I'd say
        Sexpr* lh = eval(car(args), env);
        Sexpr* rh = eval(car(cdr(args)), env);
        if(equal(lh, rh)->type == T)
-               return from_t();
-       return from_nil();
+               return cons(from_t(), rest);
+       return cons(from_nil(), rest);
 }
-Sexpr* c_not(Sexpr* b, Sexpr* env) {
-               if(CORE_NOT_ARGS != u64_get_num_args(b))
-               return b;
+Sexpr* c_not(Sexpr* b, Sexpr* rest, Sexpr* env) {
+       if(CORE_NOT_ARGS != u64_get_num_args(b))
+               return cons(b, rest);
        Sexpr* args = b->value.b.args;
        // I guess I would need the eval to check if eventually is nil
        if(eval(car(args), env)->type == NIL)
-               return from_t();
-       return from_nil();
+               return cons(from_t(), rest);
+       return cons(from_nil(), rest);
 }
-Sexpr* c_atom(Sexpr* b, Sexpr* env) {
+Sexpr* c_atom(Sexpr* b, Sexpr* rest, Sexpr* env) {
        if(CORE_ATOM_ARGS != u64_get_num_args(b))
-               return b;
+               return cons(b, rest);
        Sexpr* args = b->value.b.args;
        Sexpr* argeval = eval(car(args), env);
        while(argeval->type == QUOTE) {
                argeval = argeval->value.q;
        }
        if(argeval->type != CONS) {
-               return from_t();
+               return cons(from_t(), rest);
        }
-       return from_nil();
+       return cons(from_nil(), rest);
 }
 
 
-Sexpr* c_def(Sexpr* b, Sexpr* env) {
+Sexpr* c_def(Sexpr* b, Sexpr* rest, Sexpr* env) {
        if(CORE_DEF_ARGS != u64_get_num_args(b))
-               return b;
+               return cons(b, rest);
        Sexpr* args = b->value.b.args;
        Sexpr* val = eval(car(args), env);
        Sexpr* key = car(cdr(args));
        append_to_dict(env, key, val);
-       return val;
+       return cons(val, rest);
 }
-Sexpr* c_exit(Sexpr* b, Sexpr* env) {
+Sexpr* c_exit(Sexpr* b, Sexpr* rest, Sexpr* env) {
        if(CORE_EXIT_ARGS != u64_get_num_args(b))
-               return b;
+               return cons(b, rest);
        Sexpr* args = b->value.b.args;
        uint64_t value = car(args)->value.u;
        exit(value);
        return NULL;
 }
 
-Sexpr* x_core_dispatch(Sexpr* b, Sexpr* env) {
+Sexpr* x_core_dispatch(Sexpr* b, Sexpr* rest, Sexpr* env) {
        uint64_t code = b->value.b.opcode & 0xff;
 
        switch(code) {
        case CORE_QUOTE:
-               return c_quote(b, env);
+               return c_quote(b, rest, env);
        case CORE_CONS:
-               return c_cons(b, env);
+               return c_cons(b, rest, env);
        case CORE_CAR:
-               return c_car(b, env);
+               return c_car(b, rest, env);
        case CORE_CDR:
-               return c_cdr(b, env);
+               return c_cdr(b, rest, env);
        case CORE_IF:
-               return c_if(b, env);
+               return c_if(b, rest, env);
        case CORE_EQ:
-               return c_eq(b, env);
+               return c_eq(b, rest, env);
        case CORE_NOT:
-               return c_not(b, env);
+               return c_not(b, rest, env);
        case CORE_ATOM:
-               return c_atom(b, env);
+               return c_atom(b, rest, env);
        case CORE_DEF:
-               return c_def(b, env);
+               return c_def(b, rest, env);
        case CORE_EXIT:
-               return c_exit(b, env);
+               return c_exit(b, rest, env);
        default:
                return from_nil();
        }
 
 Sexpr* apply_builtin(Sexpr* func, Sexpr* arg, Sexpr* env);
 
 Sexpr* eval(Sexpr* s, Sexpr* dict) {
-       //printf("s: %s\n", sprint_sexpr(s));
+       printf("s: %s\n", sprint_sexpr(s));
        // non-null s
        // generally assumes that a sexpr passed to this is well-formed (ie no inapt NULLS)
        // question: does a completed builtin get evaluated here?
        } // from now on: type is cons
        Sexpr* curr = s;
        while(curr->type == CONS) {
-               if(cdr(curr)->type == NIL)
+               if(cdr(curr)->type == NIL) // this is okay to keep, yeah
                        return eval(car(curr), dict);
                if(cdr(curr)->type != CONS)
                        // need to redo, how do i eval "(f . x)" ?
                        // ^ easy, just return (f . x)
                        return curr;
                // now i need to apply actually
-               Sexpr* arg = car(cdr(curr));
+               //Sexpr* arg = car(cdr(curr));
+               Sexpr* rest = cdr(curr);
                Sexpr* func = eval(car(curr), dict);
-               Sexpr* newcar = apply_builtin(func, arg, dict);
-               Sexpr* newcdr = cdr(cdr(curr));
-               curr = cons(newcar, newcdr);
+               //Sexpr* newcar = apply_builtin(func, arg, dict);
+               //Sexpr* newcdr = cdr(cdr(curr));
+               curr = apply_builtin(func, rest, dict); // is this ok?
+               //curr = cons(newcar, newcdr);
        }
        return curr;
 }
 
-Sexpr* apply_builtin(Sexpr* func, Sexpr* arg, Sexpr* env) {
+Sexpr* apply_builtin(Sexpr* func, Sexpr* rest, Sexpr* env) {
        if(func->type != BUILTIN) {
                printf("uh oh\n");
                return from_nil(); // uhh this /should/ actually be impossible...
        Sexpr* ret = malloc(sizeof(Sexpr));
        ret->type = BUILTIN;
        ret->value.b.opcode = func->value.b.opcode;
-       ret->value.b.args = cons(arg, func->value.b.args);
+       ret->value.b.args = cons(car(rest), func->value.b.args);
        
-       return dispatch(ret, env);
+       return dispatch(ret, cdr(rest), env);
        // applies if correct no of args, just returns self otherwise
 }