summaryrefslogtreecommitdiff
path: root/src/eval.c
diff options
context:
space:
mode:
authorKai Stevenson <kai@kaistevenson.com>2023-02-18 22:29:14 -0800
committerKai Stevenson <kai@kaistevenson.com>2023-02-18 22:29:14 -0800
commit7701a8981c253cd76188999eed920d0e6101cdff (patch)
tree4127060488f9d590237249b435d9ec08d99a01ac /src/eval.c
parent552cb9bf439b9094c0ecc6b2ade0b70a926be7bb (diff)
added ref() and eval()
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c61
1 files changed, 42 insertions, 19 deletions
diff --git a/src/eval.c b/src/eval.c
index 63305b4..8319676 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -36,26 +36,12 @@ sym_t* eval(sym_t* symbol, hashtable_t* parentScope) {
pair_t p = hashtable_get_pair_recurse(parentScope, (char*)symbol->name);
if (p.key != NULL) {
sym_t* nextSym = (sym_t*)p.value;
- /* add params */
- sym_t** addedArgs = malloc(100 * sizeof(sym_t*));
- for (int i = 0; i < symbol->argCount && i < 100; i++) {
- char* keyName = malloc(6 * sizeof(char));
- strcpy(keyName, "arg");
- char index[3];
- snprintf(index, 3, "%d", i);
- strcat(keyName, index);
- sym_t* argV = eval(symbol->args[i], parentScope);
- addedArgs[i] = argV;
- pair_t argPair = init_pair(keyName, argV);
- free(keyName);
- hashtable_add_pair(newScope, argPair);
+ if (symbol->argCount > 0) {
+ returnV = eval_with_args(nextSym, symbol->args, symbol->argCount, newScope);
}
- returnV = eval(nextSym, newScope);
- /* clean up args */
- for (int i = 0; i < symbol->argCount && i < 100; i++) {
- destroy_sym(addedArgs[i]);
+ else {
+ returnV = eval(nextSym, newScope);
}
- free(addedArgs);
}
else {
printf("no matching pair in hashtable\n");
@@ -76,6 +62,28 @@ void exec_all(sym_t** symbols, int count, hashtable_t* symbolScope) {
destroy_sym(sym);
}
}
+sym_t* eval_with_args(sym_t* symbol, sym_t** args, int argCount, hashtable_t* symbolScope) {
+ sym_t** addedArgs = malloc(100 * sizeof(sym_t*));
+ for (int i = 0; i < argCount && i < 100; i++) {
+ char* keyName = malloc(6 * sizeof(char));
+ strcpy(keyName, "arg");
+ char index[3];
+ snprintf(index, 3, "%d", i);
+ strcat(keyName, index);
+ sym_t* argV = eval(args[i], symbolScope->parent);
+ addedArgs[i] = argV;
+ pair_t argPair = init_pair(keyName, argV);
+ free(keyName);
+ hashtable_add_pair(symbolScope, argPair);
+ }
+ sym_t* v = eval(symbol, symbolScope);
+ /* clean up args */
+ for (int i = 0; i < argCount && i < 100; i++) {
+ destroy_sym(addedArgs[i]);
+ }
+ free(addedArgs);
+ return v;
+}
/* internal functions?
this function has side-effects */
sym_t* try_eval_internal(sym_t* symbol, hashtable_t* symbolScope) {
@@ -86,13 +94,28 @@ sym_t* try_eval_internal(sym_t* symbol, hashtable_t* symbolScope) {
exec_all(symbol->args, symbol->argCount - 1, symbolScope);
return eval(symbol->args[symbol->argCount - 1], symbolScope);
}
+ else if (hash == get_hash("ref")) {
+ return symbol->args[0];
+ }
+ else if (hash == get_hash("eval")) {
+ hashtable_t* newScope = init_hashtable(50, symbolScope);
+ sym_t* v;
+ if (symbol->argCount > 1) {
+ v = eval_with_args(eval(symbol->args[0], symbolScope), symbol->args + 1, symbol->argCount - 1, newScope);
+ }
+ else {
+ v = eval(eval(symbol->args[0], symbolScope), newScope);
+ }
+ destroy_hashtable(newScope);
+ return v;
+ }
else if (hash == get_hash("store")) {
/* first arg is value, remaining args are names */
/* TODO: recursion for multiple pairs */
sym_t* v = eval(symbol->args[1], symbolScope);
char* k = symtos(v);
destroy_sym(v);
- sym_t* value = symbol->args[0];
+ sym_t* value = eval(symbol->args[0], symbolScope);
pair_t p = init_pair(k, (void*)value);
free(k);
hashtable_add_pair(symbolScope->parent, p);