+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "rts.h"
+
+extern struct stackval_t *start();
+
+struct stackval_t *eq(struct stackval_t *l, struct stackval_t *r)
+{
+ struct stackval_t *t = malloc(sizeof(struct stackval_t));
+ t->type = CODE;
+ t->data.code = EQ;
+ return ap(ap(t, l), r);
+}
+struct stackval_t *add(struct stackval_t *l, struct stackval_t *r)
+{
+ struct stackval_t *t = malloc(sizeof(struct stackval_t));
+ t->type = CODE;
+ t->data.code = ADD;
+ return ap(ap(t, l), r);
+}
+struct stackval_t *mul(struct stackval_t *l, struct stackval_t *r)
+{
+ struct stackval_t *t = malloc(sizeof(struct stackval_t));
+ t->type = CODE;
+ t->data.code = MUL;
+ return ap(ap(t, l), r);
+}
+
+struct stackval_t *sub(struct stackval_t *l, struct stackval_t *r)
+{
+ struct stackval_t *t = malloc(sizeof(struct stackval_t));
+ t->type = CODE;
+ t->data.code = SUB;
+ return ap(ap(t, l), r);
+}
+
+struct stackval_t *_if(struct stackval_t *l, struct stackval_t *m, struct stackval_t *r)
+{
+ struct stackval_t *t = malloc(sizeof(struct stackval_t));
+ t->type = CODE;
+ t->data.code = IF;
+ return ap(ap(ap(t, l), m), r);
+}
+
+struct stackval_t *lit(uint64_t i)
+{
+ struct stackval_t *t = malloc(sizeof(struct stackval_t));
+ t->type = LIT;
+ t->data.lit = i;
+ return t;
+}
+
+struct stackval_t *ap(struct stackval_t *l, struct stackval_t *r)
+{
+ struct stackval_t *t = malloc(sizeof(struct stackval_t));
+ t->type = AP;
+ t->data.app.l = l;
+ t->data.app.r = r;
+ return t;
+}
+
+struct stackval_t *var(void *i)
+{
+ struct stackval_t *t = malloc(sizeof(struct stackval_t));
+ t->type = FUN;
+ t->data.fun.arity = 1;
+ t->data.fun.fun = i;
+ return t;
+}
+
+void print_stackval_t(struct stackval_t *sv)
+{
+ if(sv == NULL){
+ printf("null");
+ }
+ switch(sv->type) {
+ case FUN:
+ printf("Func(%lu)", sv->data.fun.arity);
+ break;
+ case LIT:
+ printf("%llu", sv->data.lit);
+ break;
+ case CODE:
+ switch(sv->data.code){
+ case ADD:
+ printf("add");
+ break;
+ case MUL:
+ printf("mul");
+ break;
+ case EQ:
+ printf("eq");
+ break;
+ case SUB:
+ printf("sub");
+ break;
+ case IF:
+ printf("if");
+ break;
+ default:
+ printf("halp: %lu", sv->data.code);
+ break;
+ }
+ case AP:
+ printf("(");
+ print_stackval_t(sv->data.app.l);
+ printf(" ");
+ print_stackval_t(sv->data.app.r);
+ printf(")");
+ break;
+ default:
+ printf("halp: %lu", sv->type);
+ break;
+ }
+}
+
+struct stackval_t *reduce(struct stackval_t *sv)
+{
+ switch(sv->type) {
+ case FUN:
+ printf("Cannot reduce func\n");
+ return NULL;
+ case LIT:
+ return sv;
+ case CODE:
+ printf("Cannot reduce bultin\n");
+ return NULL;
+ case AP:
+ switch(sv->data.app.l->type){
+// case CODE:
+// printf("APp to code");
+// return NULL:
+ case FUN:
+ switch(sv->data.app.l->data.fun.arity){
+ case 1:
+ return ((struct stackval_t *(*)(struct stackval_t *))sv->data.app.l->data.fun.fun)(sv->data.app.r);
+ }
+ printf("App to fun");
+ return NULL;
+ default:
+ printf("Cannot apply to: ");
+ print_stackval_t(sv->data.app.l);
+ return NULL;
+ }
+ return NULL;
+ default:
+ printf("halp: %lu", sv->type);
+ return NULL;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ struct stackval_t *sv = NULL;
+ sv = start();
+ while(sv != NULL && sv->type != LIT){
+ print_stackval_t(sv);
+ printf("\n");
+ sv = reduce(sv);
+ }
+ return EXIT_SUCCESS;
+}