diff options
author | Preston Pan <preston@nullring.xyz> | 2023-01-04 19:33:28 -0800 |
---|---|---|
committer | Preston Pan <preston@nullring.xyz> | 2023-01-04 19:33:28 -0800 |
commit | 94f847851cd5fb81da18564a1b858ff20240d97a (patch) | |
tree | 1c2faa50cb7dc45b6f46b666da4e1624d9cd9877 /src/visitor.c | |
parent | 6fe77e2f20f045b89ed10c3952f8f088e9bd3d6c (diff) |
builtin functions now evaluate
Diffstat (limited to 'src/visitor.c')
-rw-r--r-- | src/visitor.c | 91 |
1 files changed, 85 insertions, 6 deletions
diff --git a/src/visitor.c b/src/visitor.c index 96eb191..acafd2e 100644 --- a/src/visitor.c +++ b/src/visitor.c @@ -38,7 +38,7 @@ bool is_built_in(ast_t *e) { /* Some string and list operations */ if (strcmp(cmp, "concat") == 0 || strcmp(cmp, "len") == 0 || strcmp(cmp, "car") == 0 || strcmp(cmp, "cdr") == 0 || - strcmp(cmp, "cons") == 0) + strcmp(cmp, "cons") == 0 || strcmp(cmp, "quote") == 0) return true; /* Comparison functions */ @@ -62,27 +62,102 @@ bool is_built_in(ast_t *e) { return false; } + /* Special symbols: car, cdr, quote, *, /, +, -, %, inc, dec, >, <, >=, <=, /=, * =, equal (for strings), input */ ast_t *eval_symbol(visitor_t *v, ast_t *e) { if (is_built_in(e)) return e; - else if (hash_table_exists(v->eval_table, e->string_value)) - return hash_table_get(v->eval_table, e->string_value); + /* first, it looks in the stack frame for a variable */ else if (hash_table_exists(stack_peek(v->stack_frame), e->string_value)) return hash_table_get(stack_peek(v->stack_frame), e->string_value); + /* Then the variables that have already been evaluated */ + else if (hash_table_exists(v->eval_table, e->string_value)) + return hash_table_get(v->eval_table, e->string_value); + + /* then it goes into the symbol table, evaluates the variable if it finds it + * and puts it in the list of variables that have already been evaluated */ else if (hash_table_exists(v->symbol_table, e->string_value)) { ast_t *unevaled = hash_table_get(v->symbol_table, e->string_value); ast_t *eval = eval_expr(v, unevaled); hash_table_add(v->eval_table, e->string_value, eval); return eval; } else - return e; + printf("DEBUG 2\n"); + eval_error(v, e); } -ast_t *eval_list(visitor_t *v, ast_t *e) {} +/* Helper function to get the size of an AST linked list; useful for checking + * parameter number */ +int get_list_size(ast_t *root) { + if (root->type != AST_PAIR) + return -1; + int size = 0; + ast_t *cur = root; + while (cur->cdr != NULL) { + size++; + cur = cur->cdr; + } + return size; +} + +ast_t *eval_list(visitor_t *v, ast_t *e) { + ast_t *function = eval_expr(v, e->car); + ast_t *args = e->cdr; + int arg_size; + int cmp = get_list_size(args); + + /* BUILT-IN FUNCTIONS */ + if (function->type == AST_SYMBOL) { + if (strcmp(function->string_value, "+") == 0) { + if (cmp != 2) + eval_error(v, e); + + ast_t *arg1 = eval_expr(v, args->car); + ast_t *arg2 = eval_expr(v, args->cdr->car); + + if ((arg1->type == AST_INT) && (arg2->type == AST_INT)) { + return init_ast_int(arg1->int_value + arg2->int_value); + } else if ((arg1->type == AST_INT) && (arg2->type == AST_FLOAT)) { + return init_ast_float(arg1->int_value + arg2->float_value); + } else if ((arg1->type == AST_FLOAT) && (arg2->type == AST_INT)) { + return init_ast_float(arg1->float_value + arg2->int_value); + } else if ((arg1->type == AST_FLOAT) && (arg2->type) == AST_FLOAT) { + return init_ast_float(arg1->float_value + arg2->float_value); + } + } + } + + /* Checking that the parameters are actually valid */ + if (function->type != AST_FUNCTION) + eval_error(v, e->car); + + arg_size = get_list_size(function->car); + + if (arg_size != cmp) + eval_error(v, e->car); + + hash_table_t *stack_frame = init_hash_table(512); + + ast_t *cur_arg_name = function->car; + ast_t *cur_arg = args; + char *name; + ast_t *evaled_arg; + while (cur_arg != NULL && cur_arg_name != NULL) { + name = cur_arg_name->car->string_value; + evaled_arg = eval_expr(v, cur_arg->car); + hash_table_add(stack_frame, name, evaled_arg); + cur_arg_name = cur_arg_name->cdr; + cur_arg = cur_arg->cdr; + } + stack_push(v->stack_frame, stack_frame); + ast_t *res = eval_expr(v, function->cdr); + stack_frame = stack_pop(v->stack_frame); + hash_table_free(stack_frame); + return res; +} ast_t *eval_expr(visitor_t *v, ast_t *e) { if (is_self_evaluating(e)) @@ -92,6 +167,7 @@ ast_t *eval_expr(visitor_t *v, ast_t *e) { else if (e->type == AST_SYMBOL) return eval_symbol(v, e); else { + printf("DEBUG\n"); eval_error(v, e); } } @@ -109,4 +185,7 @@ ast_t *eval(visitor_t *v) { return root; } -void eval_error(visitor_t *v, ast_t *e) { exit(1); } +void eval_error(visitor_t *v, ast_t *e) { + printf("ERROR: something went wrong with the visitor.\n"); + exit(1); +} |