aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/csx.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/src/csx.c b/src/csx.c
new file mode 100644
index 0000000..b6b0d38
--- /dev/null
+++ b/src/csx.c
@@ -0,0 +1,167 @@
+#include "csx.h"
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+
+enum { type_nil, type_pair, type_string, type_atom, type_fn };
+static int *type(char *p) { return (int *) (p - sizeof(int)); }
+static void type_shift(void *p) { *(char **)p += sizeof(int); }
+static void *type_alloc(int t, int content_size)
+{
+ int *res = malloc(sizeof(int) + content_size);
+ *res = t;
+ type_shift(&res);
+ return res;
+}
+
+
+struct deflist {
+ char *atom;
+ void *data;
+ struct deflist *next;
+};
+
+static struct state {
+ struct deflist *atoms;
+} csx;
+static int csx_to_init = 0;
+
+static void *nil;
+
+
+static void adddef(struct deflist **l, const char *atom, void *data)
+{
+ struct deflist *old = *l;
+ *l = malloc(sizeof(**l));
+ (*l)->next = old;
+ (*l)->atom = scopy(atom);
+ (*l)->data = data;
+}
+
+static void *csx_fn_new(void *fn, void *userdata, int size)
+{
+ void *res = malloc(sizeof(fn) + sizeof(int) + size);
+ *(void **)res = fn;
+ (char *)res += sizeof(fn);
+ *(int *)res = type_fn;
+ typeshift(&res);
+ if (userdata && size) memcpy(res, userdata, size);
+ return res;
+}
+
+static void *define(void *userdata, struct csx_pair *data)
+{ /* TODO! */
+ int t = *type(data);
+ if (t != type_pair) return nil;
+ t = *type(data->car);
+ if (t == type_atom) {
+ struct csx_pair *cdr = data->cdr;
+ if (*type(cdr) != type_pair || *type(cdr->cdr) != type_nil)
+ return nil;
+ return define_constant(data->car, cdr->cdr);
+ }
+ return define_function(data->car, data->cdr);
+}
+
+/* TODO append, cdr, ... */
+
+static void csx_init()
+{
+ if (!csx_to_init) csx_free();
+ csx.atoms = 0;
+
+ nil = type_alloc(type_nil, 0);
+ adddef(csx.atoms, "append", csx_fn_new(append, 0, 0));
+ adddef(csx.atoms, "define", csx_fn_new(define, 0, 0));
+ adddef(csx.atoms, "cdr", csx_fn_new(cdr, 0, 0));
+ adddef(csx.atoms, "ifx", csx_fn_new(ifx, 0, 0));
+ adddef(csx.atoms, "not", csx_fn_new(not, 0, 0));
+}
+
+void csx_free()
+{
+ free(nil);
+ /* free everything allocated */
+ csx_to_init = 0;
+}
+
+
+struct csx_pair *csx_pair_new(void *car, void *cdr)
+{
+ struct csx_pair *res =type_alloc(type_pair, sizeof(*res));
+ res->car = car;
+ res->cdr = cdr;
+ return res;
+}
+
+
+struct csx_pair *csx_list(void *head, ...)
+{
+ struct csx_pair *res;
+ va_list args;
+ if (csx_to_init) csx_init();
+ if (!head) return nil;
+
+ res = csx_pair_new(head, nil);
+ va_start(args, head);
+ for (head = va_arg(args, void *); head; head = va_arg(args, void *)) {
+ res->cdr = csx_pair_new(head, nil);
+ }
+ va_end(args);
+ return res;
+}
+
+char *csx_string(const char *string)
+{
+ int strsize;
+ void *res;
+ if (csx_to_init) csx_init();
+ strsize = strlen(string) + 1;
+ res = type_alloc(type_string, strsize);
+ memcpy(res, string, strsize);
+ return res;
+}
+
+char *csx_atom(const char *name)
+{
+ int namesize;
+ void *res;
+ if (csx_to_init) csx_init();
+ namesize = strlen(name) + 1;
+ res = type_alloc(type_atom, namesize);
+ memcpy(res, name, namesize);
+ return res;
+}
+
+
+static void *lookup(struct deflist *d, char *atom)
+{
+ if (!d) return nil;
+ if (!strcmp(d->atom, atom)) return d->data;
+ return lookup(d->next, atom);
+}
+
+void *eval_fn(void *fn, void *args)
+{ /* TODO! */
+ /* function : type :> userdata */
+ return 0;
+}
+
+static void *eval_pair(struct csx_pair *pair)
+{
+ void *fn;
+ int t = *type(pair->car);
+ if (t == type_fn) fn = pair->car;
+ else fn = csx_evaluate(pair->car);
+ return eval_fn(fn, pair->cdr);
+}
+
+void *csx_evaluate(void *expression)
+{
+ int t = *type(expression);
+ if (t == type_atom) return lookup(csx.atoms, expression);
+ if (t != type_pair) return nil;
+ return eval_pair(expression);
+}