#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
}