diff --git a/include/ast.h b/include/ast.h
index 5d5f272..be33c53 100644
--- a/include/ast.h
+++ b/include/ast.h
@@ -3,13 +3,20 @@
 
 #include "lexer.h"
 
+#define DEFAULT_STMTS_SIZE 512
+#define DEFAULT_ARGS_SIZE 255
+
 /*
-   expression → literal | unary | binary | grouping ;
-   literal   → NUMBER | STRING | "true" | "false" | "nil" ;
-   grouping  → "(" expression ")" ;
-   unary     → ( "-" | "!" ) expression ;
-   binary    → expression operator expression ;
-   operator  → "==" | "!=" | "<" | "<=" | ">" | ">=" | "+" | "-" | "*" | "/" ;
+expression → equality ;
+equality   → comparison ( ( "!=" | "==" ) comparison )* ;
+comparison → term ( ( ">" | ">=" | "<" | "<=" ) term )* ;
+term       → factor ( ( "-" | "+" ) factor )* ;
+factor     → unary ( ( "/" | "*" ) unary )* ;
+unary      → ( "!" | "-" ) unary | primary ;
+primary    → NUMBER | STRING | "true" | "false" | "nil" | "(" expression ")" ;
+statement      → exprStmt | ifStmt | printStmt | block ;
+ifStmt         → "if" "(" expression ")" statement ( "else" statement )? ;
+block          → "{" declaration* "}" ;
 */
 
 typedef enum {
@@ -32,18 +39,68 @@ typedef enum {
 	VAL_NIL,
 	VAL_NUMBER,
 	VAL_STRING,
+	VAL_FN,
 } value_type_t;
 
+typedef enum {
+	STMT_BLOCK,
+	STMT_CLASS,
+	STMT_EXPR,
+	STMT_FUN,
+	STMT_IF,
+	STMT_PRINT,
+	STMT_VAR,
+	STMT_WHILE,
+} stmt_type_t;
+
+typedef enum {
+	FN_NATIVE,
+	FN_CUSTOM,
+} fn_type_t;
+
+typedef struct expr_t expr_t;
+typedef struct value_t value_t;
+typedef struct stmt_t stmt_t;
+typedef struct fn_t fn_t;
+
 typedef struct {
+	expr_t **arguments;
+	int length;
+	int capacity;
+} arg_array_t;
+
+typedef struct {
+	value_t **arguments;
+	int length;
+	int capacity;
+} val_array_t;
+
+typedef struct {
+	stmt_t **statements;
+	int length;
+	int capacity;
+} stmt_array_t;
+
+struct value_t {
 	value_type_t type;
 	union {
 		int boolean;
 		double number;
 		char *string;
+		fn_t *function;
 	} as;
-} value_t;
+};
 
-typedef struct expr_t {
+typedef struct ht_t ht_t;
+
+struct fn_t {
+	fn_type_t type;
+	int arity;
+	stmt_t *stmt;
+	value_t *(*call)(stmt_t *stmt, val_array_t *arguments, ht_t *env);
+};
+
+struct expr_t {
 	expr_type_t type;
 	int line;
 	union {
@@ -59,7 +116,7 @@ typedef struct expr_t {
 		struct {
 			struct expr_t *callee;
 			token_t paren;
-			struct expr_t **arguments;
+			arg_array_t *args;
 		} call;
 		struct {
 			struct expr_t *object;
@@ -69,7 +126,7 @@ typedef struct expr_t {
 			struct expr_t *expression;
 		} grouping;
 		struct {
-			value_t value;
+			value_t *value;
 		} literal;
 		struct {
 			token_t operator;
@@ -96,7 +153,49 @@ typedef struct expr_t {
 			token_t name;
 		} variable;
 	} as;
-} expr_t;
+};
+
+struct stmt_t {
+	stmt_type_t type;
+	union {
+		struct {
+			stmt_array_t *statements;
+		} block;
+		struct {
+			token_t name;
+			token_t superclass;
+			struct stmt_t **methods;
+		} class;
+		struct {
+			expr_t *expression;
+		} expr;
+		struct {
+			token_t name;
+			array_t *params;
+			struct stmt_t *body;
+		} function;
+		struct {
+			expr_t *condition;
+			struct stmt_t *then_branch;
+			struct stmt_t *else_branch;
+		} _if;
+		struct {
+			expr_t *expression;
+		} print;
+		struct {
+			token_t keyword;
+			expr_t *value;
+		} _return;
+		struct {
+			token_t name;
+			expr_t *initializer;
+		} variable;
+		struct {
+			expr_t *condition;
+			struct stmt_t *body;
+		} _while;
+	} as;
+};
 
 expr_t *create_binary_expr(token_t *operator, expr_t *left, expr_t *right);
 expr_t *create_unary_expr(token_t *operator, expr_t *right);
@@ -105,6 +204,7 @@ expr_t *create_grouping_expr(expr_t *expression);
 expr_t *create_variable_expr(token_t *name);
 expr_t *create_assign_expr(expr_t *name, expr_t *value);
 expr_t *create_logical_expr(token_t *operator, expr_t *left, expr_t *right);
+expr_t *create_call_expr(expr_t *callee, token_t *paren, arg_array_t *args);
 void print_ast(expr_t *expr);
 
 #endif
diff --git a/include/env.h b/include/env.h
index 9da5d39..25bcaa3 100644
--- a/include/env.h
+++ b/include/env.h
@@ -13,10 +13,10 @@ typedef struct ht_t {
 #define DEFAULT_HT_SIZE 50
 
 ht_t *ht_init(ht_t *env);
-void ht_add(ht_t *ht, char *name, value_t value);
+void ht_add(ht_t *ht, char *name, value_t *value);
 value_t *ht_get(ht_t *ht, token_t *name, int check_enclosing);
-void ht_replace(ht_t *ht, char *name, value_t value);
-void ht_assign(ht_t *ht, token_t *name, value_t value);
+void ht_replace(ht_t *ht, char *name, value_t *value);
+void ht_assign(ht_t *ht, token_t *name, value_t *value);
 void ht_free(ht_t *ht);
 
 #endif
diff --git a/include/interpreter.h b/include/interpreter.h
index a2672f8..e3a241e 100644
--- a/include/interpreter.h
+++ b/include/interpreter.h
@@ -3,11 +3,11 @@
 
 #include "ast.h"
 #include "env.h"
-#include "stmt.h"
 
+void free_val(value_t *value);
 void runtime_error(const char *message, int line);
-value_t evaluate(expr_t *expr, ht_t *env);
-void print_value(value_t value);
-void evaluate_statements(stmt_array_t *array, ht_t *env);
+value_t *evaluate(expr_t *expr, ht_t *env);
+void print_value(value_t *value);
+void interpret(stmt_array_t *array);
 
 #endif
diff --git a/include/lexer.h b/include/lexer.h
index f6f2e29..aa3a785 100644
--- a/include/lexer.h
+++ b/include/lexer.h
@@ -41,6 +41,7 @@ typedef struct {
     int capacity;
 } array_t;
 
+void token_add(array_t *array, token_t token);
 array_t *tokenize(char *filename);
 void print_tokens(token_t *tokens);
 void free_array(array_t *array);
diff --git a/include/parser.h b/include/parser.h
index 004c476..57fd4bc 100644
--- a/include/parser.h
+++ b/include/parser.h
@@ -1,19 +1,8 @@
 #ifndef PARSER_H
 #define PARSER_H
 
-/*
-expression → equality ;
-equality   → comparison ( ( "!=" | "==" ) comparison )* ;
-comparison → term ( ( ">" | ">=" | "<" | "<=" ) term )* ;
-term       → factor ( ( "-" | "+" ) factor )* ;
-factor     → unary ( ( "/" | "*" ) unary )* ;
-unary      → ( "!" | "-" ) unary | primary ;
-primary    → NUMBER | STRING | "true" | "false" | "nil" | "(" expression ")" ;
-*/
-
 #include "ast.h"
 #include "lexer.h"
-#include "stmt.h"
 
 stmt_array_t *parse(token_t *tks);
 expr_t *parse_expr(token_t *tks);
diff --git a/include/stmt.h b/include/stmt.h
deleted file mode 100644
index af2bdba..0000000
--- a/include/stmt.h
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef STMT_H
-#define STMT_H
-
-#include "ast.h"
-#include "lexer.h"
-
-#define DEFAULT_STMTS_SIZE 512
-
-/*
-statement      → exprStmt | ifStmt | printStmt | block ;
-ifStmt         → "if" "(" expression ")" statement
-               ( "else" statement )? ;
- block          → "{" declaration* "}" ;
-*/
-
-typedef enum {
-	STMT_BLOCK,
-	STMT_CLASS,
-	STMT_EXPR,
-	STMT_FUN,
-	STMT_IF,
-	STMT_PRINT,
-	STMT_VAR,
-	STMT_WHILE,
-} stmt_type_t;
-
-typedef struct stmt_t stmt_t;
-
-typedef struct {
-	stmt_t **statements;
-	int length;
-	int capacity;
-} stmt_array_t;
-
-struct stmt_t {
-	stmt_type_t type;
-	union {
-		struct {
-			stmt_array_t *statements;
-		} block;
-		struct {
-			token_t name;
-			token_t superclass;
-			struct stmt_t **methods;
-		} class;
-		struct {
-			expr_t *expression;
-		} expr;
-		struct {
-			token_t name;
-			array_t *params;
-			struct stmt_t **body;
-		} function;
-		struct {
-			expr_t *condition;
-			struct stmt_t *then_branch;
-			struct stmt_t *else_branch;
-		} _if;
-		struct {
-			expr_t *expression;
-		} print;
-		struct {
-			token_t keyword;
-			expr_t *value;
-		} _return;
-		struct {
-			token_t name;
-			expr_t *initializer;
-		} variable;
-		struct {
-			expr_t *condition;
-			struct stmt_t *body;
-		} _while;
-	} as;
-};
-
-#endif 
diff --git a/src/ast.c b/src/ast.c
index 4a5cdb5..e85be2b 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -35,28 +35,29 @@ expr_t *create_literal_expr(token_t *token)
 	expr_t *expr = malloc(sizeof(expr_t));
 	expr->type = EXPR_LITERAL;
 	expr->line = token->line;
+	expr->as.literal.value = malloc(sizeof(value_t));
 	switch (token->type) {
 		case TOKEN_NUMBER:
-			expr->as.literal.value.type = VAL_NUMBER;
+			expr->as.literal.value->type = VAL_NUMBER;
 			double num;
 			sscanf(token->value, "%lf", &num);
-			expr->as.literal.value.as.number = num;
+			expr->as.literal.value->as.number = num;
 			break;
 
 		case TOKEN_NIL:
-			expr->as.literal.value.type = VAL_NIL;
-			expr->as.literal.value.as.number = 0;
+			expr->as.literal.value->type = VAL_NIL;
+			expr->as.literal.value->as.number = 0;
 			break;
 
 		case TOKEN_TRUE:
 		case TOKEN_FALSE:
-			expr->as.literal.value.type = VAL_BOOL;
-			expr->as.literal.value.as.boolean = token->type == TOKEN_TRUE;
+			expr->as.literal.value->type = VAL_BOOL;
+			expr->as.literal.value->as.boolean = token->type == TOKEN_TRUE;
 			break;
 
 		case TOKEN_STRING:
-			expr->as.literal.value.type = VAL_STRING;
-			expr->as.literal.value.as.string = strdup(token->value);
+			expr->as.literal.value->type = VAL_STRING;
+			expr->as.literal.value->as.string = strdup(token->value);
 			break;
 
 		default:
@@ -113,14 +114,27 @@ expr_t *create_logical_expr(token_t *operator, expr_t *left, expr_t *right)
 	return expr;
 }
 
+expr_t *create_call_expr(expr_t *callee, token_t *paren, arg_array_t *args)
+{
+	expr_t *expr = malloc(sizeof(expr_t));
+	expr->type = EXPR_CALL;
+	expr->line = paren->line;
+	expr->as.call.callee = callee;
+	expr->as.call.paren.type = paren->type;
+	expr->as.call.paren.value = strdup(paren->value);
+	expr->as.call.paren.line = paren->line;
+	expr->as.call.args = args;
+	return expr;
+}
+
 void print_ast(expr_t *expr)
 {
 	if (!expr)
 		return;
 	if (expr->type == EXPR_LITERAL) {
-		switch (expr->as.literal.value.type) {
+		switch (expr->as.literal.value->type) {
 			case VAL_BOOL:
-				printf("%s", expr->as.literal.value.as.boolean ? "true" : "false");
+				printf("%s", expr->as.literal.value->as.boolean ? "true" : "false");
 				break;
 
 			case VAL_NIL:
@@ -128,7 +142,7 @@ void print_ast(expr_t *expr)
 				break;
 
 			case VAL_NUMBER:;
-				double value = expr->as.literal.value.as.number;
+				double value = expr->as.literal.value->as.number;
 				if (value == (int) value) {
 					printf("%.1f", value);
 				} else {
@@ -137,7 +151,11 @@ void print_ast(expr_t *expr)
 				break;
 
 			case VAL_STRING:
-				printf("%s", expr->as.literal.value.as.string);
+				printf("%s", expr->as.literal.value->as.string);
+				break;
+
+			case VAL_FN:
+				printf("<native fn>");
 				break;
 		}
 	} else if (expr->type == EXPR_BINARY) {
diff --git a/src/env.c b/src/env.c
index 03bbe96..9af008f 100644
--- a/src/env.c
+++ b/src/env.c
@@ -5,6 +5,8 @@
 #include "env.h"
 #include "interpreter.h"
 
+void free_statement(stmt_t *stmt);
+
 ht_t *ht_init(ht_t *env)
 {	
 	ht_t *ht = malloc(sizeof(ht_t) * DEFAULT_HT_SIZE);
@@ -28,7 +30,7 @@ unsigned int hash(char *key)
 	return h;
 }
 
-void ht_add(ht_t *ht, char *name, value_t value)
+void ht_add(ht_t *ht, char *name, value_t *value)
 {
 	unsigned int idx = hash(name) % DEFAULT_HT_SIZE;
 	/* Linear probing for collision resolution */
@@ -36,11 +38,14 @@ void ht_add(ht_t *ht, char *name, value_t value)
 		int probe_idx = (idx + i) % DEFAULT_HT_SIZE;
 		if (!ht[probe_idx].name) {
 			ht[probe_idx].name = strdup(name);
-			ht[probe_idx].value.type = value.type;
-			if (value.type == VAL_STRING) {
-				ht[probe_idx].value.as.string = strdup(value.as.string);
+			ht[probe_idx].value.type = value->type;
+			if (value->type == VAL_STRING) {
+				ht[probe_idx].value.as.string = strdup(value->as.string);
+			} else if (value->type == VAL_FN) {
+				ht[probe_idx].value.as.function = malloc(sizeof(fn_t));
+				memcpy(ht[probe_idx].value.as.function, value->as.function, sizeof(fn_t));
 			} else {
-				ht[probe_idx].value.as = value.as;
+				ht[probe_idx].value.as = value->as;
 			}
 			return;
 		} else {
@@ -56,8 +61,15 @@ value_t *ht_get(ht_t *ht, token_t *name, int check_enclosing)
 	/* Linear probing to search for the key */
 	for (int i = 0; i < DEFAULT_HT_SIZE; i++) {
 		int probe_idx = (idx + i) % DEFAULT_HT_SIZE;
-		if (ht[probe_idx].name && !strcmp(ht[probe_idx].name, name->value))
-			return &ht[probe_idx].value;
+		if (ht[probe_idx].name && !strcmp(ht[probe_idx].name, name->value)) {
+			value_t *val = malloc(sizeof(value_t));
+			memcpy(val, &ht[probe_idx].value, sizeof(value_t));
+			if (val->type == VAL_STRING) {
+				val->as.string = strdup(ht[probe_idx].value.as.string);
+			}
+
+			return val;
+		}
 	}
 	if (check_enclosing) {
 		if (ht->enclosing) {
@@ -73,7 +85,7 @@ value_t *ht_get(ht_t *ht, token_t *name, int check_enclosing)
 	return NULL;
 }
 
-void ht_replace(ht_t *ht, char *name, value_t value)
+void ht_replace(ht_t *ht, char *name, value_t *value)
 {
 	unsigned int idx = hash(name) % DEFAULT_HT_SIZE;
 
@@ -87,20 +99,22 @@ void ht_replace(ht_t *ht, char *name, value_t value)
 			if (ht[probe_idx].value.type == VAL_STRING) {
 				free(ht[probe_idx].value.as.string);
 			}
-			ht[probe_idx].value.type = value.type;
-			ht[probe_idx].value.as = value.as;
-			if (value.type == VAL_STRING) {
-				ht[probe_idx].value.as.string = strdup(value.as.string);
+			ht[probe_idx].value.type = value->type;
+			ht[probe_idx].value.as = value->as;
+			if (value->type == VAL_STRING) {
+				ht[probe_idx].value.as.string = strdup(value->as.string);
 			}
 			return;
 		}
 	}
 }
 
-void ht_assign(ht_t *ht, token_t *name, value_t value)
+void ht_assign(ht_t *ht, token_t *name, value_t *value)
 {
-	if (ht_get(ht, name, 0)) {
+	value_t *val = ht_get(ht, name, 0);
+	if (val) {
 		ht_replace(ht, name->value, value);
+		free_val(val);
 		return;
 	}
 	if (ht->enclosing) {
@@ -119,6 +133,8 @@ void ht_free(ht_t *ht)
 			free(ht[i].name);
 			if (ht[i].value.type == VAL_STRING) {
 				free(ht[i].value.as.string);
+			} else if (ht[i].value.type == VAL_FN) {
+				free(ht[i].value.as.function);
 			}
 		}
 	}
diff --git a/src/interpreter.c b/src/interpreter.c
index de8780b..cdb8fea 100644
--- a/src/interpreter.c
+++ b/src/interpreter.c
@@ -1,7 +1,8 @@
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
+#include <time.h>
 
 #include "ast.h"
 #include "env.h"
@@ -9,12 +10,30 @@
 #include "lexer.h"
 #include "parser.h"
 
-value_t visit_literal(expr_t *expr)
+void evaluate_statement(stmt_t *stmt, ht_t *env);
+
+void free_val(value_t *value)
 {
-	return expr->as.literal.value;
+	if (!value)
+		return;
+	if (value->type == VAL_STRING) {
+		if (value->as.string) {
+			free(value->as.string);
+		}
+	} else if (value->type == VAL_FN) {
+
+	}
+	free(value);
 }
 
-value_t visit_grouping(expr_t *expr, ht_t *env)
+value_t *visit_literal(expr_t *expr)
+{
+	value_t *val = malloc(sizeof(value_t));
+	memcpy(val, expr->as.literal.value, sizeof(value_t));
+	return val;
+}
+
+value_t *visit_grouping(expr_t *expr, ht_t *env)
 {
 	return evaluate(expr->as.grouping.expression, env);
 }
@@ -26,56 +45,66 @@ void runtime_error(const char *message, int line)
 	exit(70);
 }
 
-value_t visit_binary(expr_t *expr, ht_t *env)
+value_t *visit_binary(expr_t *expr, ht_t *env)
 {
 	token_type_t op_type = expr->as.binary.operator.type;
-	value_t right = evaluate(expr->as.binary.right, env);
-	value_t left = evaluate(expr->as.binary.left, env);
+	value_t *right = evaluate(expr->as.binary.right, env);
+	value_t *left = evaluate(expr->as.binary.left, env);
 
 	// Arithmetic
-	if (left.type == VAL_NUMBER && right.type == VAL_NUMBER) {
-		value_t result = {.type = VAL_NUMBER};
+	if (left->type == VAL_NUMBER && right->type == VAL_NUMBER) {
+		value_t *result = malloc(sizeof(value_t));
+		result->type = VAL_NUMBER;
 		switch (op_type) {
 			case TOKEN_PLUS:
-				result.as.number = left.as.number + right.as.number;
+				result->as.number = left->as.number + right->as.number;
+				free_val(left);
+				free_val(right);
 				return result;
 
 			case TOKEN_MINUS:
-				result.as.number = left.as.number - right.as.number;
+				result->as.number = left->as.number - right->as.number;
+				free_val(left);
+				free_val(right);
 				return result;
 
 			case TOKEN_STAR:
-				result.as.number = left.as.number * right.as.number;
+				result->as.number = left->as.number * right->as.number;
+				free_val(left);
+				free_val(right);
 				return result;
 
 			case TOKEN_SLASH:
-				if (right.as.number == 0) {
+				if (right->as.number == 0) {
 					runtime_error("Division by zero.", expr->line);
 				}
-				result.as.number = left.as.number / right.as.number;
+				result->as.number = left->as.number / right->as.number;
+				free_val(left);
+				free_val(right);
 				return result;
 			default:
 				break;
 		}
+		free_val(result);
 	}
 
 	// Comparison
 	if (op_type == TOKEN_EQUAL_EQUAL || op_type == TOKEN_BANG_EQUAL) {
 		int is_equal;
-		if (left.type != right.type) {
+		if (left->type != right->type) {
 			is_equal = 0;
 		} else {
-			switch (left.type) {
+			switch (left->type) {
 				case VAL_NUMBER:
-					is_equal = left.as.number == right.as.number;
+					is_equal = left->as.number == right->as.number;
 					break;
 
 				case VAL_BOOL:
-					is_equal = left.as.boolean == right.as.boolean;
+					is_equal = left->as.boolean == right->as.boolean;
 					break;
 
 				case VAL_STRING:
-					is_equal = strcmp(left.as.string, right.as.string) == 0;
+					is_equal = strcmp(left->as.string, right->as.string) == 0;
 					break;
 
 				case VAL_NIL:
@@ -87,29 +116,41 @@ value_t visit_binary(expr_t *expr, ht_t *env)
 					break;
 			}
 		}
-		value_t result = {.type = VAL_BOOL};
-		result.as.boolean = op_type == TOKEN_EQUAL_EQUAL ? is_equal : !is_equal;
+		value_t *result = malloc(sizeof(value_t));
+		result->type = VAL_BOOL;
+		result->as.boolean = op_type == TOKEN_EQUAL_EQUAL ? is_equal : !is_equal;
+		free_val(left);
+		free_val(right);
 		return result;
 	}
 
 	// Number Comparison
-	if (left.type == VAL_NUMBER && right.type == VAL_NUMBER) {
-		value_t result = {.type = VAL_BOOL };
+	if (left->type == VAL_NUMBER && right->type == VAL_NUMBER) {
+		value_t *result = malloc(sizeof(value_t));
+		result->type = VAL_BOOL;
 		switch (op_type) {
 			case TOKEN_GREATER:
-				result.as.boolean= left.as.number > right.as.number;
+				result->as.boolean = left->as.number > right->as.number;
+				free_val(left);
+				free_val(right);
 				return result;
 
 			case TOKEN_GREATER_EQUAL:
-				result.as.boolean = left.as.number >= right.as.number;
+				result->as.boolean = left->as.number >= right->as.number;
+				free_val(left);
+				free_val(right);
 				return result;
 
 			case TOKEN_LESS:
-				result.as.boolean = left.as.number < right.as.number;
+				result->as.boolean = left->as.number < right->as.number;
+				free_val(left);
+				free_val(right);
 				return result;
 
 			case TOKEN_LESS_EQUAL:
-				result.as.boolean = left.as.number <= right.as.number;
+				result->as.boolean = left->as.number <= right->as.number;
+				free_val(left);
+				free_val(right);
 				return result;
 
 			default: break;
@@ -117,40 +158,46 @@ value_t visit_binary(expr_t *expr, ht_t *env)
 	}
 
 	// String concatenation
-	if (left.type == VAL_STRING && right.type == VAL_STRING) {
+	if (left->type == VAL_STRING && right->type == VAL_STRING) {
 		if (op_type == TOKEN_PLUS) {
-			value_t result = {.type = VAL_STRING};
-			size_t left_len = strlen(left.as.string);
-			size_t right_len = strlen(right.as.string);
-			result.as.string = malloc(left_len + right_len + 1);
-			strcpy(result.as.string, left.as.string);
-			strcat(result.as.string, right.as.string);
+			value_t *result = malloc(sizeof(value_t));
+			result->type = VAL_STRING;
+			size_t left_len = strlen(left->as.string);
+			size_t right_len = strlen(right->as.string);
+			result->as.string = malloc(left_len + right_len + 1);
+			strcpy(result->as.string, left->as.string);
+			strcat(result->as.string, right->as.string);
+			free_val(left);
+			free_val(right);
 			return result;
 		}
 	}
 
 	// String/number comparisons
-	if ((left.type == VAL_STRING && right.type == VAL_NUMBER) ||
-			(left.type == VAL_NUMBER && right.type == VAL_STRING)) {
+	if ((left->type == VAL_STRING && right->type == VAL_NUMBER) ||
+			(left->type == VAL_NUMBER && right->type == VAL_STRING)) {
 		runtime_error("Operands must be numbers.", expr->line);
 	}
 
 	runtime_error("Operands must be two numbers or two strings.", expr->line);
-	return (value_t){.type = VAL_NIL};
-
+	value_t *val = malloc(sizeof(value_t));
+	val->type = VAL_NIL;
+	free_val(left);
+	free_val(right);
+	return val;
 }
 
-int is_truthy(value_t value)
+int is_truthy(value_t *value)
 {
-	switch (value.type) {
+	switch (value->type) {
 		case VAL_NIL:
 			return 0;
 
 		case VAL_BOOL:
-			return value.as.boolean;
+			return value->as.boolean;
 
 		case VAL_NUMBER:
-			if (value.as.number == 0)
+			if (value->as.number == 0)
 				return 0;
 			return 1;
 
@@ -162,45 +209,57 @@ int is_truthy(value_t value)
 	}
 }
 
-value_t visit_unary(expr_t *expr, ht_t *env)
+value_t *visit_unary(expr_t *expr, ht_t *env)
 {
-	value_t operand = evaluate(expr->as.unary.right, env);
+	value_t *operand = evaluate(expr->as.unary.right, env);
 
 	if (expr->as.unary.operator.type == TOKEN_MINUS) {
-		if (operand.type == VAL_NUMBER) {
-			value_t result = {.type = VAL_NUMBER, .as.number = -operand.as.number};
+		if (operand->type == VAL_NUMBER) {
+			value_t *result = malloc(sizeof(value_t));
+			result->type = VAL_NUMBER;
+			result->as.number = -operand->as.number;
+			free_val(operand);
 			return result;
 		} else {
 			runtime_error("Operand must be a number.", expr->line);
 		}
 	} else if (expr->as.unary.operator.type == TOKEN_BANG) {
-		value_t result = {.type = VAL_BOOL, .as.boolean = !is_truthy(operand)};
+		value_t *result = malloc(sizeof(value_t));
+		result->type = VAL_BOOL;
+		result->as.boolean = !is_truthy(operand);
+		free_val(operand);
+
 		return result;
 	}
 
-	return (value_t){.type = VAL_NIL};
+	value_t *val = malloc(sizeof(value_t));
+	val->type = VAL_NIL;
+	free_val(operand);
+	return val;
 }
 
-value_t visit_variable(expr_t *expr, ht_t *env)
+value_t *visit_variable(expr_t *expr, ht_t *env)
 {
 	value_t *val = ht_get(env, &expr->as.variable.name, 1);
 	if (val) {
-		return *val;
+		return val;
 	} else {
-		return (value_t) {.type = VAL_NIL};
+		val = malloc(sizeof(value_t));
+		val->type = VAL_NIL;
+		return val;
 	}
 }
 
-value_t visit_assign(expr_t *expr, ht_t *env)
+value_t *visit_assign(expr_t *expr, ht_t *env)
 {
-	value_t value = evaluate(expr->as.assign.value, env);
+	value_t *value = evaluate(expr->as.assign.value, env);
 	ht_assign(env, &expr->as.assign.name->as.variable.name, value);
     return value;
 }
 
-value_t visit_logical(expr_t *expr, ht_t *env)
+value_t *visit_logical(expr_t *expr, ht_t *env)
 {
-	value_t left = evaluate(expr->as.logical.left, env);
+	value_t *left = evaluate(expr->as.logical.left, env);
 
     if (expr->as.logical.operator.type == TOKEN_OR) {
       if (is_truthy(left))
@@ -213,11 +272,58 @@ value_t visit_logical(expr_t *expr, ht_t *env)
     return evaluate(expr->as.logical.right, env);
 }
 
-value_t evaluate(expr_t *expr, ht_t *env)
+void val_add(val_array_t *array, value_t *expr)
+{
+	if (array->length == array->capacity) {
+		array->capacity *= 2;
+		array->arguments = realloc(array->arguments, array->capacity * sizeof(expr_t *));
+	}
+	array->arguments[array->length++] = expr;
+}
+
+void free_vals(val_array_t *array)
+{
+	for (int i = 0; i < array->length; i++) {
+		free_val(array->arguments[i]);
+	}
+	free(array->arguments);
+	free(array);
+}
+
+value_t *visit_call(expr_t *expr, ht_t *env)
+{
+	value_t *callee = evaluate(expr->as.call.callee, env);
+	if (callee->type != VAL_FN) {
+		runtime_error("Can only call functions and classes.", expr->line);
+	}
+
+	val_array_t *arguments = malloc(sizeof(val_array_t));
+	arguments->arguments = malloc(DEFAULT_ARGS_SIZE * sizeof(value_t *));
+	arguments->length = 0;
+	arguments->capacity = DEFAULT_ARGS_SIZE;
+	
+	for (int i = 0; i < expr->as.call.args->length; i++) {
+		value_t *val = evaluate(expr->as.call.args->arguments[i], env);
+		val_add(arguments, val);
+	}
+
+	if (arguments->length != callee->as.function->arity) {
+		char err[512];
+		snprintf(err, 512, "Expected %d arguments but got %d.", callee->as.function->arity, arguments->length);
+		runtime_error(err, expr->line);
+    }
+    value_t *res = callee->as.function->call(callee->as.function->stmt, arguments, env);
+	free_vals(arguments);
+	free_val(callee);
+	return res;
+}
+
+value_t *evaluate(expr_t *expr, ht_t *env)
 {
 	if (!expr) {
-		value_t nil_value = {.type = VAL_NIL };
-		return nil_value;
+		value_t *nil = malloc(sizeof(value_t));
+		nil->type = VAL_NIL;
+		return nil;
 	}
 	switch (expr->type) {
 		case EXPR_LITERAL:
@@ -234,17 +340,19 @@ value_t evaluate(expr_t *expr, ht_t *env)
 			return visit_assign(expr, env);
 		case EXPR_LOGICAL:
 			return visit_logical(expr, env);
+		case EXPR_CALL:
+			return visit_call(expr, env);
 		default:
 			exit(65);
 			break;
 	}
 }
 
-void print_value(value_t value)
+void print_value(value_t *value)
 {
-	switch (value.type) {
+	switch (value->type) {
 		case VAL_BOOL:
-			printf("%s\n", value.as.boolean == 1 ? "true" : "false");
+			printf("%s\n", value->as.boolean == 1 ? "true" : "false");
 			break;
 
 		case VAL_NIL:
@@ -252,66 +360,22 @@ void print_value(value_t value)
 			break;
 
 		case VAL_STRING:
-			printf("%s\n", value.as.string);
+			printf("%s\n", value->as.string);
 			break;
 
 		case VAL_NUMBER:
-			if (value.as.number == (int) value.as.number) {
-				printf("%d\n", (int) value.as.number);
+			if (value->as.number == (int) value->as.number) {
+				printf("%d\n", (int) value->as.number);
 			} else {
-				printf("%g\n", value.as.number);
+				printf("%g\n", value->as.number);
 			}
 			break;
 
-		default:
-			break;
-	}
-}
-
-void evaluate_block(stmt_array_t *array, ht_t *cur_env, ht_t *scope_env)
-{
-	ht_t *previous = cur_env;
-	cur_env = scope_env;
-	evaluate_statements(array, cur_env);
-	ht_free(scope_env);
-	cur_env = previous;
-}
-
-void evaluate_statement(stmt_t *stmt, ht_t *env)
-{
-	switch (stmt->type) {
-		case STMT_IF:
-			if (is_truthy(evaluate(stmt->as._if.condition, env))) {
-				evaluate_statement(stmt->as._if.then_branch, env);
-			} else if (stmt->as._if.else_branch) {
-				evaluate_statement(stmt->as._if.else_branch, env);
-			}
-			break;
-
-		case STMT_PRINT:
-			print_value(evaluate(stmt->as.print.expression, env));
-			break;
-
-		case STMT_EXPR:
-			evaluate(stmt->as.expr.expression, env);
-			break;
-
-		case STMT_VAR: {
-			value_t value = {.type = VAL_NIL};
-			if (stmt->as.variable.initializer) {
-				value = evaluate(stmt->as.variable.initializer, env);
-			}
-			ht_add(env, stmt->as.variable.name.value, value);
-			break;
-		}
-
-		case STMT_BLOCK:
-			evaluate_block(stmt->as.block.statements, env, ht_init(env));
-			break;
-
-		case STMT_WHILE:
-			while (is_truthy(evaluate(stmt->as._while.condition, env))) {
-				evaluate_statement(stmt->as._while.body, env);
+		case VAL_FN:
+			if (value->as.function->type == FN_NATIVE) {
+				printf("<native fn>\n");
+			} else {
+				printf("<fn %s>\n", value->as.function->stmt->as.function.name.value);
 			}
 			break;
 
@@ -326,3 +390,121 @@ void evaluate_statements(stmt_array_t *array, ht_t *env)
 		evaluate_statement(array->statements[i], env);
 	}
 }
+
+void evaluate_block(stmt_array_t *array, ht_t *cur_env, ht_t *scope_env)
+{
+	ht_t *previous = cur_env;
+	cur_env = scope_env;
+	evaluate_statements(array, cur_env);
+	ht_free(scope_env);
+	cur_env = previous;
+}
+
+value_t *_clock(stmt_t *stmt, val_array_t *arguments, ht_t *env)
+{
+	value_t *val = malloc(sizeof(value_t));
+	val->type = VAL_NUMBER;
+	val->as.number = time(NULL);
+	return val;
+}
+
+value_t *_call(stmt_t *stmt, val_array_t *arguments, ht_t *env)
+{
+	ht_t *fn_env = ht_init(env);
+	for (int i = 0; i < stmt->as.function.params->length; i++) {
+		ht_add(fn_env, stmt->as.function.params->tokens[i].value, arguments->arguments[i]);
+	}
+
+	evaluate_block(stmt->as.function.body->as.block.statements, env, fn_env);
+
+    return NULL;
+}
+
+void evaluate_statement(stmt_t *stmt, ht_t *env)
+{
+	switch (stmt->type) {
+		case STMT_IF:
+			if (is_truthy(evaluate(stmt->as._if.condition, env))) {
+				evaluate_statement(stmt->as._if.then_branch, env);
+			} else if (stmt->as._if.else_branch) {
+				evaluate_statement(stmt->as._if.else_branch, env);
+			}
+			break;
+
+		case STMT_PRINT:;
+			value_t *val = evaluate(stmt->as.print.expression, env);
+			print_value(val);
+			free_val(val);
+			break;
+
+		case STMT_EXPR:;
+			value_t *res = evaluate(stmt->as.expr.expression, env);
+			free_val(res);
+			break;
+
+		case STMT_VAR: {
+			value_t *value = malloc(sizeof(value_t));
+			value->type = VAL_NIL;
+			if (stmt->as.variable.initializer) {
+				free(value);
+				value = evaluate(stmt->as.variable.initializer, env);
+			}
+			ht_add(env, stmt->as.variable.name.value, value);
+			free_val(value);
+			break;
+		}
+
+		case STMT_BLOCK:
+			evaluate_block(stmt->as.block.statements, env, ht_init(env));
+			break;
+
+		case STMT_WHILE:;
+			value_t *cond = evaluate(stmt->as._while.condition, env);
+			while (is_truthy(cond)) {
+				evaluate_statement(stmt->as._while.body, env);
+				free_val(cond);
+				cond = evaluate(stmt->as._while.condition, env);
+			}
+			free_val(cond);
+			break;
+
+		case STMT_FUN:;
+			fn_t *fn = malloc(sizeof(fn_t));
+			fn->type = FN_CUSTOM;
+			fn->arity = stmt->as.function.params->length;
+			fn->stmt = stmt;
+			fn->call = _call;
+
+			value_t *fn_val = malloc(sizeof(value_t));
+			fn_val->type = VAL_FN;
+			fn_val->as.function = fn;
+			ht_add(env, stmt->as.function.name.value, fn_val);
+			free_val(fn_val);
+			free(fn);
+			break;
+
+		default:
+			break;
+	}
+}
+
+void interpret(stmt_array_t *array)
+{
+	ht_t *env = ht_init(NULL);
+	value_t *clock_fn = malloc(sizeof(value_t));
+	clock_fn->type = VAL_FN;
+	fn_t *fn = malloc(sizeof(fn_t));
+	fn->type = FN_NATIVE;
+	fn->arity = 0;
+	/* Native function don't have body */
+	fn->stmt = NULL;
+	fn->call = _clock;
+	clock_fn->as.function = fn;
+
+	ht_add(env, "clock", clock_fn);
+	evaluate_statements(array, env);
+	ht_free(env);
+	free(clock_fn);
+	free(fn);
+	free_statements(array);
+}
diff --git a/src/parser.c b/src/parser.c
index 704c93a..321e291 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -4,11 +4,13 @@
 #include <errno.h>
 
 #include "ast.h"
+#include "interpreter.h"
 #include "lexer.h"
 #include "parser.h"
 
 int current = 0;
 token_t *tokens;
+void free_args(arg_array_t *array);
 expr_t *expression(void);
 stmt_t *expression_stmt(void);
 stmt_t *statement(void);
@@ -54,9 +56,7 @@ void free_expr(expr_t *expr)
 			break;
 
 		case EXPR_LITERAL:
-			if (expr->as.literal.value.type == VAL_STRING) {
-				free(expr->as.literal.value.as.string);
-			}
+			free(expr->as.literal.value);
 			free(expr);
 			break;
 	
@@ -78,6 +78,13 @@ void free_expr(expr_t *expr)
 			free(expr);
 			break;
 
+		case EXPR_CALL:
+			free_args(expr->as.call.args);
+			free_expr(expr->as.call.callee);
+			free(expr->as.call.paren.value);
+			free(expr);
+			break;
+
 		default:
 			break;
 	}
@@ -109,6 +116,16 @@ int check(token_type_t type)
 	return tokens[current].type == type;
 }
 
+int match(token_type_t type)
+{
+	if (check(type)) {
+		advance();
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
 token_t *consume(token_type_t type, char *message)
 {
 	if (!check(type)) {
@@ -123,21 +140,18 @@ token_t *consume(token_type_t type, char *message)
 
 expr_t *primary(void)
 {
-	if (check(TOKEN_FALSE) || check(TOKEN_TRUE) || check(TOKEN_NIL) ||
-			check(TOKEN_NUMBER) || check(TOKEN_STRING)) {
-		token_t *tok = peek();
-		advance();
+	if (match(TOKEN_FALSE) || match(TOKEN_TRUE) || match(TOKEN_NIL) ||
+			match(TOKEN_NUMBER) || match(TOKEN_STRING)) {
+		token_t *tok = previous();
 		return create_literal_expr(tok);
 	}
 
-	if (check(TOKEN_IDENTIFIER)) {
-		token_t *tok = peek();
-		advance();
+	if (match(TOKEN_IDENTIFIER)) {
+		token_t *tok = previous();
 		return create_variable_expr(tok);
 	}
 
-	if (check(TOKEN_LEFT_PAREN)) {
-		advance();
+	if (match(TOKEN_LEFT_PAREN)) {
 		expr_t *expr = expression();
 		consume(TOKEN_RIGHT_PAREN, "Expect ')' after expression.");
 		return create_grouping_expr(expr);
@@ -146,25 +160,67 @@ expr_t *primary(void)
 	return NULL;
 }
 
+void arg_add(arg_array_t *array, expr_t *expr)
+{
+	if (array->length == array->capacity) {
+		array->capacity *= 2;
+		array->arguments = realloc(array->arguments, array->capacity * sizeof(expr_t *));
+	}
+	array->arguments[array->length++] = expr;
+}
+
+void free_args(arg_array_t *array)
+{
+	for (int i = 0; i < array->length; i++) {
+		free_expr(array->arguments[i]);
+	}
+	free(array->arguments);
+	free(array);
+}
+
+expr_t *call(void)
+{
+    expr_t *expr = primary();
+	while (1) {
+		if (match(TOKEN_LEFT_PAREN)) {
+			arg_array_t *args = malloc(sizeof(arg_array_t));
+			args->arguments = malloc(DEFAULT_ARGS_SIZE * sizeof(expr_t *));
+			args->length = 0;
+			args->capacity = DEFAULT_ARGS_SIZE;
+			if (!check(TOKEN_RIGHT_PAREN)) {
+				do {
+					if (args->length >= 255) {
+						error(peek(), "Can't have more than 255 arguments.");
+					}
+					arg_add(args, expression());
+				} while (match(TOKEN_COMMA));
+			}
+			token_t *paren = consume(TOKEN_RIGHT_PAREN, "Expect ')' after arguments.");
+			expr = create_call_expr(expr, paren, args);
+		} else {
+			break;
+		}
+    }
+	return expr;
+}
+
 expr_t *unary(void)
 {
-	if (check(TOKEN_BANG) || check(TOKEN_MINUS)) {
-		token_t *operator = peek();
-		advance();
+	if (match(TOKEN_BANG) || match(TOKEN_MINUS)) {
+		token_t *operator = previous();
 		expr_t *right = unary();
 		return create_unary_expr(operator, right);
 	}
 
-	return primary();
+	return call();
 }
 
 expr_t *factor(void)
 {
 	expr_t *expr = unary();
 
-	while (check(TOKEN_SLASH) || check(TOKEN_STAR)) {
-		token_t *operator = peek();
-		advance();
+	while (match(TOKEN_SLASH) || match(TOKEN_STAR)) {
+		token_t *operator = previous();
 		expr_t *right = unary();
 		expr = create_binary_expr(operator, expr, right);
 	}
@@ -176,9 +232,8 @@ expr_t *term(void)
 {
 	expr_t *expr = factor();
 
-	while (check(TOKEN_MINUS) || check(TOKEN_PLUS)) {
-		token_t *operator = peek();
-		advance();
+	while (match(TOKEN_MINUS) || match(TOKEN_PLUS)) {
+		token_t *operator = previous();
 		expr_t *right = factor();
 		expr = create_binary_expr(operator, expr, right);
 	}
@@ -190,10 +245,9 @@ expr_t *comparison(void)
 {
 	expr_t *expr = term();
 
-	while (check(TOKEN_GREATER) || check(TOKEN_GREATER_EQUAL) || check(TOKEN_LESS)
-			|| check(TOKEN_LESS_EQUAL)) {
-		token_t *operator = peek();
-		advance();
+	while (match(TOKEN_GREATER) || match(TOKEN_GREATER_EQUAL) || match(TOKEN_LESS)
+			|| match(TOKEN_LESS_EQUAL)) {
+		token_t *operator = previous();
 		expr_t *right = term();
 		expr = create_binary_expr(operator, expr, right);
 	}
@@ -205,9 +259,8 @@ expr_t *equality(void)
 {
 	expr_t *expr = comparison();
 
-	while (check(TOKEN_BANG_EQUAL) || check(TOKEN_EQUAL_EQUAL)) {
-		token_t *operator = peek();
-		advance();
+	while (match(TOKEN_BANG_EQUAL) || match(TOKEN_EQUAL_EQUAL)) {
+		token_t *operator = previous();
 		expr_t *right = comparison();
 		expr = create_binary_expr(operator, expr, right);
 	}
@@ -219,9 +272,8 @@ expr_t *and(void)
 {
 	expr_t *expr = equality();
 
-    while (check(TOKEN_AND)) {
-		token_t *operator = peek();
-		advance();
+    while (match(TOKEN_AND)) {
+		token_t *operator = previous();
 		expr_t *right = equality();
 		expr = create_logical_expr(operator, expr, right);
     }
@@ -233,9 +285,8 @@ expr_t *or(void)
 {
 	expr_t *expr = and();
 
-    while (check(TOKEN_OR)) {
-		token_t *operator = peek();
-		advance();
+    while (match(TOKEN_OR)) {
+		token_t *operator = previous();
 		expr_t *right = and();
 		expr = create_logical_expr(operator, expr, right);
     }
@@ -247,9 +298,8 @@ expr_t *assignment(void)
 {
 	expr_t *expr = or();
 
-	if (check(TOKEN_EQUAL)) {
-		token_t *equals = peek();
-		advance();
+	if (match(TOKEN_EQUAL)) {
+		token_t *equals = previous();
 		expr_t *value = assignment();
 
 		if (expr->type == EXPR_VARIABLE) {
@@ -302,6 +352,11 @@ void free_statement(stmt_t *stmt)
 		free_expr(stmt->as._while.condition);
 		free_statement(stmt->as._while.body);
 		free(stmt);
+	} else if (stmt->type == STMT_FUN) {
+		free(stmt->as.function.name.value);
+		free_array(stmt->as.function.params);
+		free_statement(stmt->as.function.body);
+		free(stmt);
 	}
 }
 
@@ -318,10 +373,8 @@ stmt_t *for_stmt(void)
 {
 	consume(TOKEN_LEFT_PAREN, "Expect '(' after 'for'.");
 	stmt_t *initializer = NULL;
-    if (check(TOKEN_SEMICOLON)) {
-		advance();
-    } else if (check(TOKEN_VAR)) {
-		advance();
+    if (match(TOKEN_SEMICOLON)) {
+    } else if (match(TOKEN_VAR)) {
 		initializer = var_declaration();
     } else {
 		initializer = expression_stmt();
@@ -393,8 +446,7 @@ stmt_t *if_stmt(void)
 	consume(TOKEN_RIGHT_PAREN, "Expect ')' after if condition.");
 	stmt_t *then_branch = statement();
     stmt_t *else_branch = NULL;
-    if (check(TOKEN_ELSE)) {
-		advance();
+    if (match(TOKEN_ELSE)) {
 		else_branch = statement();
     }
 	stmt_t *stmt = malloc(sizeof(stmt_t));
@@ -461,36 +513,68 @@ stmt_t *expression_stmt(void)
 
 stmt_t *statement(void)
 {
-	if (check(TOKEN_FOR)) {
-		advance();
+	if (match(TOKEN_FOR)) {
 		return for_stmt();
 	}
-	if (check(TOKEN_IF)) {
-		advance();
+	if (match(TOKEN_IF)) {
 		return if_stmt();
 	}
-	if (check(TOKEN_PRINT)) {
-		advance();
+	if (match(TOKEN_PRINT)) {
 		return print_stmt();
 	}
-	if (check(TOKEN_WHILE)) {
-		advance();
+	if (match(TOKEN_WHILE)) {
 		return while_stmt();
 	}
-	if (check(TOKEN_LEFT_BRACE)) {
-		advance();
+	if (match(TOKEN_LEFT_BRACE)) {
 		return block_stmt();
 	}
 	return expression_stmt();
 }
 
+stmt_t *function(char *kind)
+{
+	char err[512];
+	snprintf(err, 512, "Expect %s name.", kind);
+	token_t *name = consume(TOKEN_IDENTIFIER, err);
+	snprintf(err, 512, "Expect '(' after %s name.", kind);
+	consume(TOKEN_LEFT_PAREN, err);
+	array_t *parameters = malloc(sizeof(array_t));
+	parameters->tokens = malloc(DEFAULT_ARGS_SIZE * sizeof(token_t));
+	parameters->length = 0;
+	parameters->capacity = DEFAULT_ARGS_SIZE;
+
+	if (!check(TOKEN_RIGHT_PAREN)) {
+		do {
+			if (parameters->length >= 255) {
+				error(peek(), "Can't have more than 255 parameters.");
+			}
+
+			token_t *param = consume(TOKEN_IDENTIFIER, "Expect parameter name.");
+			token_t param_cpy;
+			memcpy(&param_cpy, param, sizeof(token_t));
+			param_cpy.value = strdup(param->value);
+			token_add(parameters, param_cpy);
+		} while (match(TOKEN_COMMA));
+	}
+	consume(TOKEN_RIGHT_PAREN, "Expect ')' after parameters.");
+	snprintf(err, 512, "Expect '{' before %s body.", kind);
+	consume(TOKEN_LEFT_BRACE, err);
+	stmt_t *stmt = malloc(sizeof(stmt_t));
+	stmt->type = STMT_FUN;
+	stmt->as.function.name.type = name->type;
+	stmt->as.function.name.value = strdup(name->value);
+	stmt->as.function.name.line = name->line;
+	stmt->as.function.params = parameters;
+	stmt->as.function.body = block_stmt();
+	return stmt;
+}
+
 stmt_t *var_declaration(void)
 {
 	token_t *name = consume(TOKEN_IDENTIFIER, "Expect variable name.");
 
 	expr_t *initializer = NULL;
-	if (check(TOKEN_EQUAL)) {
-		advance();
+	if (match(TOKEN_EQUAL)) {
 		initializer = expression();
 	}
 
@@ -507,8 +591,10 @@ stmt_t *var_declaration(void)
 
 stmt_t *declaration(void)
 {
-	if (check(TOKEN_VAR)) {
-		advance();
+	if (match(TOKEN_FUN)) {
+		return function("function");
+	}
+	if (match(TOKEN_VAR)) {
 		return var_declaration();
 	}
 
@@ -522,7 +608,7 @@ stmt_array_t *parse(token_t *tks)
 		return NULL;
 	} else {
 		stmt_array_t *statements = malloc(sizeof(stmt_array_t));
-		statements->statements = malloc(DEFAULT_STMTS_SIZE * sizeof(stmt_t));
+		statements->statements = malloc(DEFAULT_STMTS_SIZE * sizeof(stmt_t *));
 		statements->length = 0;
 		statements->capacity = DEFAULT_STMTS_SIZE;
 		while (!end()) {
diff --git a/src/rd.c b/src/rd.c
index db608fd..6910394 100644
--- a/src/rd.c
+++ b/src/rd.c
@@ -34,18 +34,15 @@ int main(int argc, char **argv)
 		free_expr(expr);
 	} else if (!strcmp(command, "evaluate")) {
 		expr_t *expr = parse_expr(array->tokens);
-		value_t val = evaluate(expr, NULL);
+		value_t *val = evaluate(expr, NULL);
 		print_value(val);
 		free_array(array);
 		free_expr(expr);
 	} else if (!strcmp(command, "run")) {
-		ht_t *env = ht_init(NULL);
 		stmt_array_t *stmts = parse(array->tokens);
 		if (errno != 65) {
-			evaluate_statements(stmts, env);
-			ht_free(env);
+			interpret(stmts);
 			free_array(array);
-			free_statements(stmts);
 		}
 	} else {
 		fprintf(stderr, "Unknown command: %s\n", command);