+
+OPCODES: each 'page' has 256 diff opts, splits prior to that for maintainability or whatever
+
+OKAY MAIN PROBLEM NOW:
+for the builtins, I need to literally clone them all the time whenever I need a new one, or else the args pointer stays the same and it effects other calls of the function
+solution! I just initialize to null, and make a clone when I need to I guess
+
+
+NOTE ON HOW I ACTUALLY INTEND TO DO THIS
+THIS REFERRING TO HANDLING EVALUATIONS OF BUILTINS
+I think maybe a struct storing the opcode and a pointer to a sexpr representing a list of args might be the way to do it, plus a uint for num of args?
+
+also I want each individual opcode to decide whether or not and how to evaluate its own arguments
+
+
+
 So this is a poorly-named directory, since what I'm making will end up being a lisp-1...
 
 thinking about taking ideas from concatenative languages, tacit programming, and the such.
 
--- /dev/null
+
+
+#include "types.h"
+#include "sexpr.h"
+
+
+// this is where you include whatever extra sets of instructions
+
+#include "builtins/core.h"
+
+
+Sexpr* dispatch(Sexpr* b) {
+       uint64_t prefix = (b->value.b.opcode) >> 8;
+       switch(prefix) {
+       case CORE_PREFIX:
+               return x_core_dispatch(b);
+       default:
+               return from_nil();
+       }
+}
 
--- /dev/null
+#ifndef _BUILTINS_H
+#define _BUILTINS_H
+
+#include "types.h"
+
+#include "builtins/core.h"
+
+#define _HIIIII
+
+Sexpr* dispatch(Sexpr* b);
+
+
+
+#endif
 
--- /dev/null
+
+
+#include "../types.h"
+#include "../sexpr.h"
+#include "../eval.h"
+
+
+
+Sexpr* x_core_dispatch(Sexpr* s) {
+       uint64_t code = s->value.b.opcode & 0xff;
+       switch(code) {
+       case 0: // quote
+               
+       default:
+               return from_nil();
+       }
+       return from_nil();
+}
 
--- /dev/null
+
+
+#include "../types.h"
+
+// need to define
+
+#define CORE_PREFIX 0x00
+
+
+Sexpr* x_core_dispatch(Sexpr* s);
+
 
 
 Sexpr* lookup(Sexpr* dict, Sexpr* key) {
        // assumes dict well-formed
+       // returns nil if not found, returns (result) if it is
        Sexpr* node = dict;
                while(node->type != NIL) {
                        if(equal(key, car(car(node)))->type == T) {
-                               return cdr(car(node));
+                               return cons(cdr(car(node)), from_nil());
                        }
                        node = cdr(node);
        }
 
 
 #include "types.h"
 #include "sexpr.h"
+#include "dict.h"
+#include "builtins.h"
 
+Sexpr* apply_builtin(Sexpr* func, Sexpr* arg);
 
-Sexpr* eval(Sexpr* s) {
+Sexpr* eval(Sexpr* s, Sexpr* dict) {
        // 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?
        if(s == NULL) return NULL; // not needed if assumptions accurate, but yknow
        if(s->type == SYM) {
                // look up the value in the lookup table
-               return s;
+               return car(lookup(dict, s));
        }
        if(s->type != CONS) {
                return s;
        } // from now on: type is cons
-       if(cdr(s) == NULL) {
-               return car(s);
-       } // from now on: a function of some sort is being called
+       Sexpr* curr = s;
+       while(curr->type == CONS) {
+               if(cdr(curr)->type == NIL)
+                       //return eval(car(curr), dict);
+                       return car(curr);
+               if(cdr(curr)->type != CONS)
+                       // need to redo, how do i eval "(f . x)" ?
+                       return car(curr);
+               // now i need to apply actually
+               Sexpr* arg = car(cdr(curr));
+               Sexpr* func = car(curr);
+               Sexpr* newcar = apply_builtin(func, arg);
+               Sexpr* newcdr = cdr(cdr(curr));
+               curr = cons(newcar, newcdr);
+       }
+       return curr;
+}
 
-       return NULL;
+Sexpr* apply_builtin(Sexpr* func, Sexpr* arg) {
+       if(func->type != BUILTIN)
+               return from_nil(); // uhh this /should/ actually be impossible...
+       uint8_t num_args = 0;
+       Sexpr* curr = func->value.b.args;
+       while(curr->type != NIL) {
+               curr = cdr(curr);
+               num_args++;
+       }
+       Sexpr* ret = malloc(sizeof(Sexpr));
+       if(num_args < func->value.b.num_args_needed) {
+               ret->type = BUILTIN;
+               ret->value.b.opcode = func->value.b.opcode;
+               ret->value.b.num_args_needed = func->value.b.num_args_needed;
+               ret->value.b.args = cons(arg, func->value.b.args);
+       }
+       if(num_args+1 < func->value.b.num_args_needed)
+               return ret;
+       // what's left now: all the args needed are there,
+       // just gotta dispatch to whatever handles the opcode evals
+       return dispatch(ret);
 }
 
                return from_t();
        if(t == T)
                return from_t();
-
        if(t == SYM) {
                return strcmp(a->value.s, b->value.s) == 0 ? from_t() : from_nil();
        }
                snprintf(out, nbytes, "%" PRIu64 "", s->value.u);
                return out;
        }
+       else if(s->type == BUILTIN) {
+               nbytes = snprintf(NULL, 0, "%" PRIu64 "", s->value.u) + 2;
+               out = malloc(nbytes*sizeof(char));
+               out[0] = '_';
+               snprintf(out, nbytes+1, "%" PRIu64 "", s->value.u);
+               return out;
+       }
        else if(s->type == CONS) {
                Sexpr* curr_cell = s;
                size_t currsize = 2;
 
 #include "sexpr.h"
 #include "parser.h"
 #include "dict.h"
-
+#include "eval.h"
 
 
 
 
 typedef char* Symbol_t;
 typedef void* Nil_t;
 typedef void* Truth_t;
+//typedef uint64_t Builtin_t;
 
 typedef enum Sexpr_Type {
        UINT, SYM, BUILTIN, NIL, T, CONS, FEXP, FUN
        struct Sexpr* cdr;
 } Cons_t;
 
+typedef struct Builtin {
+       struct Sexpr* args;
+       uint64_t num_args_needed;
+       uint64_t opcode;
+} Builtin_t;
+
 typedef struct Closure {
        uint64_t opcode;
        uint64_t num_args;
                Fexpr_t x;
                Fun_t f;
                uint64_t u;
+               Builtin_t b;
                Symbol_t s;
                Cons_t* c;
                Nil_t n;