#include "ast.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* some slice functions */

char*
str_of_slice(slice_t slice)
{
	char* str = malloc(slice.len + 1);
	if (!str) return 0;
	strncpy(str, slice.start, slice.len);
	str[slice.len] = '\0';
	return str;
}

slice_t*
mk_slice(char* c)
{
	slice_t* s = malloc(sizeof(slice_t));
	s->start       = c;
	s->len         = strlen(c);
	s->indentation = 0;
	return s;
}

void
print_slice(slice_t* s)
{
	int i;
	for (i = 0; i < s->len; i++)
		printf("%c", s->start[i]);
}

/* expr helpers */

void
expr_print(expr_t* e)
{
	(e->print)(e->payload);
}

/* app */

void
print_app(expr_t **payload)
{
	printf("(apply ");
	expr_print(payload[0]);
	printf(" ");
	expr_print(payload[1]);
	printf(")");
}

expr_t*
mk_app(expr_t* f, expr_t* x)
{
	expr_t* e = malloc(sizeof(void*) * 4);
	e->print = (callback)&print_app;
	e->eval  = NULL;
	{
		void** v = (void**) e;
		v[2] = (void*) f;
		v[3] = (void*) x;
	}
	return e;
}

/* lam */

/* let */

/* var */

void
print_var(slice_t **s)
{
	printf("(var \"");
	print_slice(s[0]);
	printf("\")");
}

expr_t*
mk_var(ident_t* i)
{
	void** v = malloc(sizeof(void*) * 3);
	v[0] = (void*)&print_var;
	v[1] = NULL;
	v[2] = i;
	return (expr_t*) v;
}

/* annot */

/* default */

void
print_default(void* payload)
{
	printf("nil");
}

expr_t*
mk_default(void)
{
	expr_t* e = malloc(sizeof(expr_t));
	e->print = &print_default;
	e->eval  = NULL;
	return e;
}

/* for testing */

int
main(int argc, char* argv[])
{
	expr_t* e = mk_app(mk_default(), mk_var(mk_slice("foo")));
	expr_print(e);
	printf("\n");
	return 0;
}
