From 155144a82692272e9199f53c64ea92c1fac36cde Mon Sep 17 00:00:00 2001 From: Elijah Cohen Date: Thu, 8 Aug 2024 15:06:27 -0500 Subject: [PATCH] it works? need to fix some things for sure tho, especially parser --- ideas.org | 8 ++++++++ src/builtins.c | 7 +++++++ src/builtins/arithmetic.c | 40 +++++++++++++++++++++++++++++++++++++++ src/builtins/arithmetic.h | 15 +++++++++++++++ src/builtins/core.c | 38 +++++++++++++++++++++++++------------ src/eval.c | 19 ++++++++++++++----- src/repl.c | 9 +++++++-- src/sexpr.c | 27 ++++++++++++++++++++++---- src/sexpr.h | 1 + src/test.c | 1 + src/types.h | 3 ++- 11 files changed, 144 insertions(+), 24 deletions(-) create mode 100644 src/builtins/arithmetic.c create mode 100644 src/builtins/arithmetic.h diff --git a/ideas.org b/ideas.org index 00ca6f7..09d6a87 100644 --- a/ideas.org +++ b/ideas.org @@ -1,5 +1,13 @@ +okay current problem is figuring out the right way to do 'quote'... I think I just need a special thing in my sexpr typedef for a quoted form.. should be easy enough + +ALL THE PLACES WHERE I NEED TO GO THROUGH ALL THE TYPES: +sprint_sexpr +eval + +is that it? + 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 diff --git a/src/builtins.c b/src/builtins.c index 088012c..f7a5761 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -8,6 +8,7 @@ // this is where you include whatever extra sets of instructions #include "builtins/core.h" +#include "builtins/arithmetic.h" #include #include @@ -18,6 +19,8 @@ Sexpr* dispatch(Sexpr* b, Sexpr* env) { switch(prefix) { case CORE_PREFIX: return x_core_dispatch(b, env); + case ARITH_PREFIX: + return x_arith_dispatch(b, env); default: return from_nil(); } @@ -35,6 +38,10 @@ uint64_t u64_get_num_args(Sexpr* b) { Sexpr* load_env(Sexpr* env) { + append_to_dict(env, from_sym("nil"), from_nil()); + append_to_dict(env, from_sym("t"), from_t()); Sexpr* newenv = load_core_env(env); + newenv = load_arith_env(newenv); + append_to_dict(env, from_sym("asdf"), from_uint(5455)); return newenv; } diff --git a/src/builtins/arithmetic.c b/src/builtins/arithmetic.c new file mode 100644 index 0000000..c612272 --- /dev/null +++ b/src/builtins/arithmetic.c @@ -0,0 +1,40 @@ + +#include "../types.h" +#include "../builtins.h" +#include "../sexpr.h" +#include "../eval.h" +#include "../dict.h" +#include "arithmetic.h" + +#include +#include + + +Sexpr* a_plus(Sexpr* b, Sexpr* env) { + if(ARITH_PLUS_ARGS != u64_get_num_args(b)) { + return b; + } + Sexpr* args = b->value.b.args; + uint64_t m = eval(car(args), env)->value.u; + uint64_t n = eval(car(cdr(args)), env)->value.u; + return from_uint(m + n); +} + +Sexpr* x_arith_dispatch(Sexpr* b, Sexpr* env) { + uint64_t code = b->value.b.opcode & 0xff; + + switch(code) { + case ARITH_PLUS: + return a_plus(b, env); + default: + return from_nil(); + } + return from_nil(); +} + +Sexpr* load_arith_env(Sexpr* env) { + Sexpr* a_plus = from_opcode((ARITH_PREFIX << 8) | ARITH_PLUS); + append_to_dict(env, from_sym("+"), a_plus); + + return env; +} diff --git a/src/builtins/arithmetic.h b/src/builtins/arithmetic.h new file mode 100644 index 0000000..6c3fa8f --- /dev/null +++ b/src/builtins/arithmetic.h @@ -0,0 +1,15 @@ +#ifndef _B_ARITH_H +#define _B_ARITH_H + +#include "../types.h" + +#define ARITH_PREFIX 0x01 + + +#define ARITH_PLUS 0x00 +#define ARITH_PLUS_ARGS 2 + +Sexpr* x_arith_dispatch(Sexpr* s, Sexpr* env); +Sexpr* load_arith_env(Sexpr* env); + +#endif diff --git a/src/builtins/core.c b/src/builtins/core.c index 01b5cc3..9c4ebf8 100644 --- a/src/builtins/core.c +++ b/src/builtins/core.c @@ -10,10 +10,13 @@ #include #include +#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); + //return car(b->value.b.args); + return from_quote(car(b->value.b.args)); } // redo the rest of these... @@ -21,30 +24,30 @@ 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)); + Sexpr* _cdr = car(args); + Sexpr* _car = car(cdr(args)); return cons(_car, _cdr); } 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)); + return car(eval(car(args), env)); } 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)); + return cdr(eval(car(args), env)); } 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* falsy = car(args); Sexpr* truthy = car(cdr(args)); - Sexpr* falsy = car(cdr(cdr(args))); + Sexpr* cond = car(cdr(cdr(args))); if(eval(cond, env)->type != NIL) return truthy; else @@ -76,19 +79,26 @@ 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) + Sexpr* argeval = eval(car(args), env); + while(argeval->type == QUOTE) { + argeval = argeval->value.q; + } + if(argeval->type != CONS) { return from_t(); + } return from_nil(); } Sexpr* c_def(Sexpr* b, Sexpr* env) { - if(CORE_ATOM_ARGS != u64_get_num_args(b)) + if(CORE_DEF_ARGS != u64_get_num_args(b)) return b; Sexpr* args = b->value.b.args; - Sexpr* val = eval(car(cdr(args)), env); - append_to_dict(env, car(args), cdr(args)); + Sexpr* val = eval(car(args), env); + Sexpr* key = car(cdr(args)); + printf("val: %s\n", sprint_sexpr(val)); + printf("key: %s\n", sprint_sexpr(key)); + append_to_dict(env, key, val); return val; } Sexpr* c_exit(Sexpr* b, Sexpr* env) { @@ -122,6 +132,8 @@ Sexpr* x_core_dispatch(Sexpr* b, Sexpr* env) { return c_atom(b, env); case CORE_DEF: return c_def(b, env); + case CORE_EXIT: + return c_exit(b, env); default: return from_nil(); } @@ -148,5 +160,7 @@ Sexpr* load_core_env(Sexpr* env) { append_to_dict(env, from_sym("atom"), c_atom); Sexpr* c_def = from_opcode(CORE_DEF); append_to_dict(env, from_sym("def"), c_def); + Sexpr* c_exit = from_opcode(CORE_EXIT); + append_to_dict(env, from_sym("exit"), c_exit); return env; } diff --git a/src/eval.c b/src/eval.c index 534f3e6..b4a1618 100644 --- a/src/eval.c +++ b/src/eval.c @@ -10,17 +10,24 @@ Sexpr* apply_builtin(Sexpr* func, Sexpr* arg, Sexpr* env); Sexpr* eval(Sexpr* s, Sexpr* dict) { + 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? 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 car(lookup(dict, s)); + Sexpr* lookedup = lookup(dict, s); + if(lookedup->type == NIL) { + printf("%s not defined\n", s->value.s); + return lookedup; + } + return car(lookedup); } if(s->type != CONS) { return s; } // from now on: type is cons + //printf("idk\n"); Sexpr* curr = s; while(curr->type == CONS) { if(cdr(curr)->type == NIL) @@ -28,10 +35,11 @@ Sexpr* eval(Sexpr* s, Sexpr* dict) { return car(curr); if(cdr(curr)->type != CONS) // need to redo, how do i eval "(f . x)" ? - return car(curr); + // ^ easy, just return (f . x) + return curr; // now i need to apply actually Sexpr* arg = car(cdr(curr)); - Sexpr* func = car(curr); + Sexpr* func = eval(car(curr), dict); Sexpr* newcar = apply_builtin(func, arg, dict); Sexpr* newcdr = cdr(cdr(curr)); curr = cons(newcar, newcdr); @@ -40,9 +48,10 @@ Sexpr* eval(Sexpr* s, Sexpr* dict) { } Sexpr* apply_builtin(Sexpr* func, Sexpr* arg, Sexpr* env) { - if(func->type != BUILTIN) + 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; diff --git a/src/repl.c b/src/repl.c index 94ebb17..5329ccd 100644 --- a/src/repl.c +++ b/src/repl.c @@ -15,7 +15,6 @@ int main(int argc, char** argv) { - printf("makefile functional lol\n"); Sexpr* env = init_dict(); load_env(env); @@ -26,8 +25,14 @@ int main(int argc, char** argv) { if(input == NULL) return 0; linenoiseHistoryAdd(input); + printf("asdf1\n"); Sexpr* in = parse(input); - Sexpr* out = eval(in, env); + printf("asdf2\n"); + if(in == NULL) { + printf("bad input\n"); + } + printf("- -%s\n", sprint_sexpr(in)); + Sexpr* out = eval(car(in), env); printf(" - %s\n", sprint_sexpr(out)); linenoiseFree(input); } diff --git a/src/sexpr.c b/src/sexpr.c index 14e7fdb..e2d4652 100644 --- a/src/sexpr.c +++ b/src/sexpr.c @@ -45,6 +45,13 @@ Sexpr* from_opcode(uint64_t u) { return ret; } +Sexpr* from_quote(Sexpr* s) { + Sexpr* ret = malloc(sizeof(Sexpr)); + ret->type = QUOTE; + ret->value.q = s; + return ret; +} + Sexpr* cons(Sexpr* car, Sexpr* cdr) { Cons_t* c = malloc(sizeof(Cons_t)); Sexpr* s = malloc(sizeof(Sexpr)); @@ -71,9 +78,18 @@ Sexpr* equal(Sexpr* a, Sexpr* b) { return from_t(); if(t == T) return from_t(); - if(t == SYM) { + if(t == SYM) return strcmp(a->value.s, b->value.s) == 0 ? from_t() : from_nil(); - } + if(t == UINT) + return (a->value.u == b->value.u) ? from_t() : from_nil(); + if(t == BUILTIN) + if(a->value.b.opcode == b->value.b.opcode) + return equal(a->value.b.args, b->value.b.args); + if(t == QUOTE) + return equal(a->value.q, b->value.q); + if(t == CONS) + if(equal(car(a), car(b))->type == T) + return equal(cdr(a), cdr(b)); // leaving everything else off for... reasons return from_nil(); } @@ -135,8 +151,11 @@ char* sprint_sexpr(Sexpr* s) { 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; + snprintf(out + 1, nbytes, "%" PRIu64 "", s->value.u); + return out; + } + else if(s->type == QUOTE) { + return sprint_sexpr(s->value.q); } else if(s->type == CONS) { Sexpr* curr_cell = s; diff --git a/src/sexpr.h b/src/sexpr.h index 8946091..274dd3e 100644 --- a/src/sexpr.h +++ b/src/sexpr.h @@ -8,6 +8,7 @@ Sexpr* from_t(); Sexpr* from_sym(char* s); Sexpr* from_uint(uint64_t u); Sexpr* from_opcode(uint64_t u); +Sexpr* from_quote(Sexpr* s); Sexpr* cons(Sexpr* car, Sexpr* cdr); Sexpr* car(Sexpr* s); diff --git a/src/test.c b/src/test.c index 3fc6d14..f11ee37 100644 --- a/src/test.c +++ b/src/test.c @@ -65,6 +65,7 @@ void test_parser() { printf("_: %s\n", sprint_sexpr(parse("457"))); printf("_: %s\n", sprint_sexpr(parse("a b c d e"))); printf("_: %s\n", sprint_sexpr(parse("(a b (3 2 (5) c) d (e f) g)"))); + //printf("_: %s\n", sprint_sexpr(parse("(457"))); } void test_eq() { diff --git a/src/types.h b/src/types.h index d1e30c4..4d2e6c1 100644 --- a/src/types.h +++ b/src/types.h @@ -12,7 +12,7 @@ typedef void* Nil_t; typedef void* Truth_t; typedef enum Sexpr_Type { - UINT, SYM, BUILTIN, NIL, T, CONS + UINT, SYM, BUILTIN, NIL, T, CONS, QUOTE } Sexpr_Type; typedef struct Cons { @@ -35,6 +35,7 @@ typedef struct Sexpr { Cons_t* c; Nil_t n; Truth_t t; + struct Sexpr* q; } value; } Sexpr; -- 2.39.2