From c5ebed5ae4263748dfc2b1d25ca2327743dc3f8b Mon Sep 17 00:00:00 2001 From: Elijah Cohen Date: Wed, 24 Jul 2024 23:18:05 -0500 Subject: [PATCH] boutta reshape the dict stuff majorly this is mostly some core functions --- .gitignore | 1 + ideas.org | 15 ++++++ src/builtins.c | 27 +++++++--- src/builtins.h | 4 +- src/builtins/core.c | 119 ++++++++++++++++++++++++++++++++++++++------ src/builtins/core.h | 21 ++++++++ src/eval.c | 24 +++------ src/eval.h | 17 +++++++ src/repl.c | 20 ++++++++ src/sexpr.c | 8 +++ src/sexpr.h | 2 + src/types.h | 1 - 12 files changed, 215 insertions(+), 44 deletions(-) create mode 100644 .gitignore create mode 100644 src/eval.h create mode 100644 src/repl.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e4e5f6c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*~ \ No newline at end of file diff --git a/ideas.org b/ideas.org index f2dc099..00ca6f7 100644 --- a/ideas.org +++ b/ideas.org @@ -1,5 +1,20 @@ + +shit do i make the env just a consed version of itself then update the car whenever i want a state update? That seems like an iffy but promising idea + +okay! I think I might be able to wing it where you pass a pointer to an object that stores your env, and what it gets passed to is a function that + + + +major problem now is that I haven't figured out how I want to store the environment? I think that I might have to make a special sort of 'engine' type datastructure, which loads its own 'def' procedure + +Oh okay a bonus of that is that I can leave a 'page' of opcodes for doing things with the environment or whatever. I can perhaps open i/o ports that way, or spawn multiple processes, or run gc, or god knows what else + +do I even need gc yet? I might just be able to track what I use in time, maybe i'll end up with something more akin to arc? +potential for avoiding auto-deletion of saved things: clone everything as it's used lol + + OPCODES: each 'page' has 256 diff opts, splits prior to that for maintainability or whatever OKAY MAIN PROBLEM NOW: diff --git a/src/builtins.c b/src/builtins.c index 002897d..70e5b04 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -2,14 +2,18 @@ #include "types.h" #include "sexpr.h" +#include "dict.h" // this is where you include whatever extra sets of instructions #include "builtins/core.h" +#include +#include -Sexpr* apply(Sexpr* b, Sexpr* env) { + +Sexpr* dispatch(Sexpr* b, Sexpr* env) { uint64_t prefix = (b->value.b.opcode) >> 8; switch(prefix) { case CORE_PREFIX: @@ -19,11 +23,18 @@ Sexpr* apply(Sexpr* b, Sexpr* env) { } } -Sexpr* append_arg(Sexpr* b, Sexpr* arg) { - // where b better be a builtin - Sexpr* ret = malloc(sizeof(Sexpr)); - ret->type = BUILTIN; - ret->value.b.opcode = b->value.b.opcode; - ret->value.b.args = cons(arg, b->value.b.args); - return ret; +uint64_t u64_get_num_args(Sexpr* b) { + uint64_t curr_num = 0; + Sexpr* args = b->value.b.args; + while(args->type != NIL) { + curr_num++; + args = cdr(args); + } + return curr_num; +} + + +Sexpr* load_into_env(Sexpr* env) { + Sexpr* newenv = load_core_env(env); + return newenv; } diff --git a/src/builtins.h b/src/builtins.h index f5aa583..1ad8b0c 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -7,8 +7,8 @@ #define _HIIIII -Sexpr* apply(Sexpr* b, Sexpr* env); -Sexpr* append_arg(Sexpr* b, Sexpr* arg); +Sexpr* dispatch(Sexpr* b, Sexpr* env); +uint64_t u64_get_num_args(Sexpr* b); #endif diff --git a/src/builtins/core.c b/src/builtins/core.c index f6d14a6..f71ba4e 100644 --- a/src/builtins/core.c +++ b/src/builtins/core.c @@ -1,43 +1,130 @@ #include "../types.h" +#include "../builtins.h" #include "../sexpr.h" #include "../eval.h" +#include "../dict.h" +#include "core.h" -Sexpr* c_quote(Sexpr* args) { - return car(args); +#include + +Sexpr* c_quote(Sexpr* b, Sexpr* env) { + if(CORE_QUOTE_ARGS != u64_get_num_args(b)) + return b; + return car(b->value.b.args); } -Sexpr* c_cons(Sexpr* args) { + +// redo the rest of these... +Sexpr* c_cons(Sexpr* b, Sexpr* env) { + if(CORE_CONS_ARGS != u64_get_num_args(b)) + return b; + Sexpr* args = b->value.b.args; Sexpr* _car = car(args); Sexpr* _cdr = car(cdr(args)); return cons(_car, _cdr); } -Sexpr* c_car(Sexpr* args) { +Sexpr* c_car(Sexpr* b, Sexpr* env) { + if(CORE_CAR_ARGS != u64_get_num_args(b)) + return b; + Sexpr* args = b->value.b.args; return car(car(args)); } -Sexpr* c_cdr(Sexpr* args) { +Sexpr* c_cdr(Sexpr* b, Sexpr* env) { + if(CORE_CDR_ARGS != u64_get_num_args(b)) + return b; + Sexpr* args = b->value.b.args; return cdr(car(args)); } -Sexpr* c_if(Sexpr* args) { +Sexpr* c_if(Sexpr* b, Sexpr* env) { + if(CORE_IF_ARGS != u64_get_num_args(b)) + return b; + Sexpr* args = b->value.b.args; + Sexpr* cond = car(args); Sexpr* truthy = car(cdr(args)); Sexpr* falsy = car(cdr(cdr(args))); - + if(eval(cond, env)->type != NIL) + return truthy; + else + return falsy; + // uhhh am I sure about this one? + // the lack of evals is perhaps a little suspect... +} +Sexpr* c_eq(Sexpr* b, Sexpr* env) { + if(CORE_EQ_ARGS != u64_get_num_args(b)) + return b; + 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(); +} +Sexpr* c_not(Sexpr* b, Sexpr* env) { + if(CORE_NOT_ARGS != u64_get_num_args(b)) + return b; + 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(); } +Sexpr* c_atom(Sexpr* b, Sexpr* env) { + if(CORE_ATOM_ARGS != u64_get_num_args(b)) + return b; + Sexpr* args = b->value.b.args; + // need eval here for same reasons as not + if(eval(car(args), env)->type != CONS) + return from_t(); + return from_nil(); +} + -//Sexpr* c_quote(Sexpr* args); -//Sexpr* c_cons(Sexpr* args); +Sexpr* x_core_dispatch(Sexpr* b, Sexpr* env) { + uint64_t code = b->value.b.opcode & 0xff; -Sexpr* x_core_dispatch(Sexpr* s, Sexpr* env) { - uint64_t code = s->value.b.opcode & 0xff; - Sexpr* args = s->value.b.args; switch(code) { - case 0: // quote - return c_quote(args); - case 1: // cons - return c_cons(args); + case CORE_QUOTE: + return c_quote(b, env); + case CORE_CONS: + return c_cons(b, env); + case CORE_CAR: + return c_car(b, env); + case CORE_CDR: + return c_cdr(b, env); + case CORE_IF: + return c_if(b, env); + case CORE_EQ: + return c_eq(b, env); + case CORE_NOT: + return c_not(b, env); + case CORE_ATOM: + return c_atom(b, env); default: return from_nil(); } return from_nil(); } + + +Sexpr* load_core_env(Sexpr* env) { + Sexpr* c_quote = from_opcode(CORE_QUOTE); + append_to_dict(env, from_sym("quote"), c_quote); + Sexpr* c_cons = from_opcode(CORE_CONS); + append_to_dict(env, from_sym("cons"), c_cons); + Sexpr* c_car = from_opcode(CORE_CAR); + append_to_dict(env, from_sym("car"), c_car); + Sexpr* c_cdr = from_opcode(CORE_CDR); + append_to_dict(env, from_sym("cdr"), c_cdr); + Sexpr* c_if = from_opcode(CORE_IF); + append_to_dict(env, from_sym("if"), c_if); + Sexpr* c_eq = from_opcode(CORE_EQ); + append_to_dict(env, from_sym("eq"), c_eq); + Sexpr* c_not = from_opcode(CORE_NOT); + append_to_dict(env, from_sym("not"), c_not); + Sexpr* c_atom = from_opcode(CORE_ATOM); + append_to_dict(env, from_sym("atom"), c_atom); + return env; +} diff --git a/src/builtins/core.h b/src/builtins/core.h index bbcc74d..c6963ae 100644 --- a/src/builtins/core.h +++ b/src/builtins/core.h @@ -1,3 +1,5 @@ +#ifndef _B_CORE_H +#define _B_CORE_H #include "../types.h" @@ -6,6 +8,25 @@ #define CORE_PREFIX 0x00 +#define CORE_QUOTE 0x00 +#define CORE_QUOTE_ARGS 1 +#define CORE_CONS 0x01 +#define CORE_CONS_ARGS 2 +#define CORE_CAR 0x02 +#define CORE_CAR_ARGS 1 +#define CORE_CDR 0x03 +#define CORE_CDR_ARGS 1 +#define CORE_IF 0x04 +#define CORE_IF_ARGS 3 +#define CORE_EQ 0x05 +#define CORE_EQ_ARGS 2 +#define CORE_NOT 0x06 +#define CORE_NOT_ARGS 1 +#define CORE_ATOM 0x07 +#define CORE_ATOM_ARGS 1 + Sexpr* x_core_dispatch(Sexpr* s, Sexpr* env); +Sexpr* load_core_env(Sexpr* env); +#endif diff --git a/src/eval.c b/src/eval.c index e3a42dd..534f3e6 100644 --- a/src/eval.c +++ b/src/eval.c @@ -32,7 +32,7 @@ Sexpr* eval(Sexpr* s, Sexpr* dict) { // now i need to apply actually Sexpr* arg = car(cdr(curr)); Sexpr* func = car(curr); - Sexpr* newcar = apply_builtin(func, arg); + Sexpr* newcar = apply_builtin(func, arg, dict); Sexpr* newcdr = cdr(cdr(curr)); curr = cons(newcar, newcdr); } @@ -42,22 +42,12 @@ Sexpr* eval(Sexpr* s, Sexpr* dict) { Sexpr* apply_builtin(Sexpr* func, Sexpr* arg, Sexpr* env) { 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 + ret->type = BUILTIN; + ret->value.b.opcode = func->value.b.opcode; + ret->value.b.args = cons(arg, func->value.b.args); + return dispatch(ret, env); + // applies if correct no of args, just returns self otherwise } diff --git a/src/eval.h b/src/eval.h new file mode 100644 index 0000000..db625cc --- /dev/null +++ b/src/eval.h @@ -0,0 +1,17 @@ +#ifndef _EVAL_H +#define _EVAL_H + +#include "types.h" +#include +#include + +// everything needed for the dictionary + +// key type is string, value type is sexpr, hash range is uint64_t + +Sexpr* eval(Sexpr* s, Sexpr* env); +Sexpr* apply_builtin(Sexpr* func, Sexpr* arg, Sexpr* env); + + + +#endif diff --git a/src/repl.c b/src/repl.c new file mode 100644 index 0000000..0d83371 --- /dev/null +++ b/src/repl.c @@ -0,0 +1,20 @@ + + +#include + +#include "types.h" +#include "eval.h" +#include "dict.h" + + + +Sexpr* stepl(char* str, Sexpr* env) { + Sexpr* toeval = parse(str); + +} + +int main(int argc, char** argv) { + printf("makefile functional\n"); + + return 0; +} diff --git a/src/sexpr.c b/src/sexpr.c index fbe4994..e8e00e2 100644 --- a/src/sexpr.c +++ b/src/sexpr.c @@ -37,6 +37,14 @@ Sexpr* from_uint(uint64_t u) { return ret; } +Sexpr* from_opcode(uint64_t u) { + Sexpr* ret = malloc(sizeof(Sexpr)); + ret->type = BUILTIN; + ret->value.b.opcode = u; + ret->value.b.args = from_nil(); + return ret; +} + Sexpr* cons(Sexpr* car, Sexpr* cdr) { Cons_t* c = malloc(sizeof(Cons_t)); Sexpr* s = malloc(sizeof(Sexpr)); diff --git a/src/sexpr.h b/src/sexpr.h index 335c4b9..873da1d 100644 --- a/src/sexpr.h +++ b/src/sexpr.h @@ -11,6 +11,8 @@ Sexpr* from_t(); Sexpr* from_sym(char* s); Sexpr* from_uint(uint64_t u); + +Sexpr* from_opcode(uint64_t u); Sexpr* cons(Sexpr* car, Sexpr* cdr); diff --git a/src/types.h b/src/types.h index caf3484..33cf151 100644 --- a/src/types.h +++ b/src/types.h @@ -24,7 +24,6 @@ typedef struct Cons { typedef struct Builtin { struct Sexpr* args; - uint64_t num_args_needed; uint64_t opcode; } Builtin_t; -- 2.39.2