summaryrefslogtreecommitdiff
path: root/eval.c
blob: b1d4e0a7f5ac3c4bd17b4beac1ec5e4f6b87923e (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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "eval.h"
#include "hashtable.h"
#include "parse.h"

hashtable_t* ht;
const int hashtableSize = 1000;
const int trueVal = 1;
sym_t trueSym = {LITERAL, INT, (void*)&trueVal, NULL, 0};
const int falseVal = 0;
sym_t falseSym = {LITERAL, INT, (void*)&falseVal, NULL, 0};

void init_eval() {
	ht = init_hashtable(hashtableSize);
}
/* TODO: read base hashtable from file to allow modularity
pair value value? */
void exec_all(sym_t** symbols, int count) {
	for (int i = 0; i < count; i++) {
		/* dispose of result */
		eval(symbols[i]);
	}
}
sym_t* eval(sym_t* symbol) {
	if (symbol->province == LITERAL) {
		return(symbol);
	}
	else if (symbol->province == KEY_REF) {
		sym_t* ir = try_eval_internal(symbol);
		if (ir != NULL) {
			return ir;
		}
		else {
			/* not an internal function, search hashtable for
			next symbol */
			/* TODO: scope */
			pair_t* p = hashtable_get_pair(ht, (char*)symbol->name);
			if (p != NULL) {
				return eval((sym_t*)p->value);
			}
			else {
				printf("no matching pair in hashtable\n");
				return NULL;
			}
		}
	}
	else {
		printf("no symbol province\n");
		return NULL;
	}
}
/* internal functions?
this function has side-effects */
sym_t* try_eval_internal(sym_t* symbol) {
	unsigned int hash = get_hash((char*)symbol->name);
	/* TODO: return last arg. that's the function return line */
	if (hash == get_hash("root")) {
		/* execute all args as roots */
		exec_all(symbol->args, symbol->argCount);
		return &trueSym;
	}
	else if (hash == get_hash("store")) {
		/* TODO: scope */
		/* first arg is value, remaining args are names */
		/* TODO: recursion for multiple pairs */
		char* k = symtos(eval(symbol->args[1]));
		sym_t* v = symbol->args[0];
		pair_t* p = init_pair(k, (void*)v);
		hashtable_add_pair(ht, p);
		return &trueSym;
	}
	/* TODO: release()/free() method? */
	else if (hash == get_hash("eq")) {
		litType_t type = NO_TYPE;
		void* lastVal = NULL;
		for (int i  = 0; i < symbol->argCount; i++) {
			sym_t* v = eval(symbol->args[i]);
			/* initialize */
			if (type == NO_TYPE) {
				type = v->litType;
				lastVal = v->name;
			}
			else {
				/* interpret type */
				if (type == INT) {
					if (symtoi(v) != *((int*)lastVal)) {
						return &falseSym;
					}
				}
				if (type == STRING) {
					if (strcmp(symtos(v), (char*)lastVal) != 0) {
						return &falseSym;
					}
				}
				/* TODO: float */
			}
		}
		return &trueSym;
	}
	else if (hash == get_hash("if")) {
		sym_t* v = eval(symbol->args[0]);
		if (symtoi(v) != 0) {
			exec_all(symbol->args + 1, symbol->argCount - 1);
			return &trueSym;
		}
		return &falseSym;
	}
	else if (hash == get_hash("not")) {
		sym_t* v = eval(symbol->args[0]);
		int b = symtoi(v);
		return b ? &falseSym : &trueSym;
	}
	else if (hash == get_hash("print")) {
		sym_t* v = eval(symbol->args[0]);
		switch (v->litType) {
			case NO_TYPE:
				break;
			case INT:
				printf("%d\n", symtoi(v));
				break;
			case FLOAT:
				break;
			case STRING:
				printf("%s\n", symtos(v));
				break;
		}
		return &trueSym;
	}
	else {
		return NULL;
	}
}