#ifndef TREEIFY_H
#define TREEIFY_H

#include <context.h>

enum node_type {
	EXPRESSION,
	DECLARATION,
	DEFINITION,
};

/**
 * Expressions
 */

// (*f* x y)
struct node_expression_identifier {
	ctx_string name; // f
};

enum node_expression_parameter_type {
	PARAM_TYPE_IDENT,
	PARAM_TYPE_EXPRESSION,
};

// (f *x* *y* *(expr)*)
struct node_expression_parameter {
	enum node_expression_parameter_type type;
	union {
		ctx_string name; // x or y
		struct node_expression *expression; // (expr)
	} data;
};

// (*f x y*)
struct node_expression {
	struct node_expression_identifier *callee; // f
	struct node_expression_parameter *parameters; // x y
	size_t parameter_count;
};

/**
 * Declarations
 */

// *f* u32 u32 -> *u32*
struct node_declaration_callee {
	ctx_string name; // f
	ctx_string type; // u32
};

// f *u32* *u32* -> u32
struct node_declaration_parameter {
	ctx_string type; // u32
};

// *f u32 u32 -> u32*
struct node_declaration {
	struct node_declaration_callee callee; // f
	struct node_declaration_parameter *parameters; // u32 u32 OR NULL
	size_t parameter_count;
};

/**
 * Definitions
 */

// *f* a b : expr
struct node_definition_callee {
	ctx_string name;
};

// f *a* *b* : expr
struct node_definition_parameter {
	ctx_string name; // u32
};

// *f a b : expr*
struct node_definition {
	struct node_definition_callee callee; // f
	struct node_definition_parameter *parameters; // a b
	size_t parameter_count;
	struct node_expression expression; // expr
};

struct node {
	enum node_type type;
	struct node *prev;
	struct node *next;
	void *data;
};

struct node *tree_create(void);
void tree_destroy(struct node *tree);
void tree_add(struct ctx *ctx, enum node_type type, void *data);

void treeify(struct ctx *ctx);

#endif