summaryrefslogtreecommitdiffstats
path: root/eval.c
blob: 4e593d97caf29db691536f12572a0d131429562c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include "eval.h"
#include "types.h"


LISP_OBJECT *eval_apply(LISP_OBJECT *lisp_list, HashMap *env)
{
	if(lisp_list == NULL || lisp_list->type != LISP_TYPE_LIST)
		return lisp_list;

	LISP_OBJECT *symbol = lisp_list->value.list->ptr;
	List *args = lisp_list->value.list->next;

	LISP_OBJECT *func = hash_map_find(env, symbol->value.symbol)->value;

	if(func->type != LISP_TYPE_FUNC)
		return lisp_list;

	List *tmp = lisp_list->value.list;
	lisp_list->value.list = args;
	LISP_OBJECT *ret = func->value.func(lisp_list);
	lisp_list->value.list = tmp;
	return ret;
}

LISP_OBJECT *eval_prepere_args(LISP_OBJECT *lisp_list, HashMap *env)
{
	if(lisp_list == NULL || lisp_list->type != LISP_TYPE_LIST)
		return lisp_list;

	LISP_OBJECT *args = lisp_object_make_list();
	List **args_list = &args->value.list;

	List *list = lisp_list->value.list;
	LISP_OBJECT *obj = NULL;

	while(list)
	{
		obj = list->ptr;
		if(obj->type==LISP_TYPE_LIST)
			obj = eval(obj, env);

		*args_list = list_push(*args_list, obj);
		list = list->next;
	}

	*args_list = list_reverse(*args_list);

	return eval_apply(args, env);
}


LISP_OBJECT *eval(LISP_OBJECT *lisp_obj, HashMap *env)
{
	if(lisp_obj == NULL)
		return NULL;

	if(lisp_obj->type == LISP_TYPE_LIST)
		return eval_prepere_args(lisp_obj, env);

	return lisp_obj;
}