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
135
136
137
138
|
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "eval.h"
#include "hashtable.h"
#include "parse.h"
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};
/* TODO: read base hashtable from file to allow modularity
pair value value? */
sym_t* eval(sym_t* symbol, hashtable_t* parentScope) {
if (symbol->province == LITERAL) {
return(symbol);
}
else if (symbol->province == KEY_REF) {
sym_t* returnV = NULL;
/* entering new scope, so create a new table */
hashtable_t* newScope = init_hashtable(500, parentScope);
sym_t* ir = try_eval_internal(symbol, newScope);
if (ir != NULL) {
returnV = ir;
}
else {
/* not an internal function, search hashtable for
next symbol */
/* TODO: scope */
pair_t p = hashtable_get_pair_recurse(parentScope, (char*)symbol->name);
if (p.key != NULL) {
returnV = eval((sym_t*)p.value, newScope);
}
else {
printf("no matching pair in hashtable\n");
}
}
/* clear new scope, then return */
destroy_hashtable(newScope);
return returnV;
}
else {
printf("no symbol province\n");
return NULL;
}
}
void exec_all(sym_t** symbols, int count, hashtable_t* symbolScope) {
for (int i = 0; i < count; i++) {
eval(symbols[i], symbolScope);
destroy_sym(symbols[i]);
}
}
/* internal functions?
this function has side-effects */
sym_t* try_eval_internal(sym_t* symbol, hashtable_t* symbolScope) {
unsigned int hash = get_hash((char*)symbol->name);
if (hash == get_hash("root")) {
/* execute all args as roots except for the last */
/* return last arg, that's the function return line */
exec_all(symbol->args, symbol->argCount - 1, symbolScope);
return eval(symbol->args[symbol->argCount - 1], symbolScope);
}
else if (hash == get_hash("arg")) {
/* get positional arg in current scope */
return NULL;
}
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], symbolScope));
sym_t* v = symbol->args[0];
pair_t p = init_pair(k, (void*)v);
hashtable_add_pair(symbolScope->parent, 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], symbolScope);
/* 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], symbolScope);
if (symtoi(v) != 0) {
exec_all(symbol->args + 1, symbol->argCount - 1, symbolScope);
return &trueSym;
}
return &falseSym;
}
else if (hash == get_hash("not")) {
sym_t* v = eval(symbol->args[0], symbolScope);
int b = symtoi(v);
return b ? &falseSym : &trueSym;
}
else if (hash == get_hash("print")) {
sym_t* v = eval(symbol->args[0], symbolScope);
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;
}
}
|