aboutsummaryrefslogtreecommitdiff
path: root/src/interpreter.c
diff options
context:
space:
mode:
authorFlavian Kaufmann <flavian@flaviankaufmann.ch>2025-05-25 15:54:50 +0200
committerFlavian Kaufmann <flavian@flaviankaufmann.ch>2025-05-25 15:54:50 +0200
commit330e46236b421ffb8fe263caf91196f4cd1114c5 (patch)
tree09b3df77fca2d23dacef64f6962e9a1afd5b4d29 /src/interpreter.c
parentde59dbd1773dff06051b7b604977bcb2803ada4f (diff)
downloadimp-330e46236b421ffb8fe263caf91196f4cd1114c5.tar.gz
imp-330e46236b421ffb8fe263caf91196f4cd1114c5.zip
[cleanup] codebase cleanup
Diffstat (limited to 'src/interpreter.c')
-rw-r--r--src/interpreter.c421
1 files changed, 67 insertions, 354 deletions
diff --git a/src/interpreter.c b/src/interpreter.c
index c0678b7..b04a293 100644
--- a/src/interpreter.c
+++ b/src/interpreter.c
@@ -4,248 +4,18 @@
#include <stdio.h>
#include <assert.h>
-#include "hashmap.h"
-
-typedef void *YY_BUFFER_STATE;
-extern FILE *yyin;
-extern IMP_ASTNode *ast_root;
-extern int yyparse(void);
-extern void yyrestart (FILE*);
-extern YY_BUFFER_STATE yy_scan_string(const char*);
-extern void yy_delete_buffer(YY_BUFFER_STATE);
-
-typedef struct Context{
- hashmap_t var_table;
- hashmap_t proc_table;
-} Context;
-
-
-static IMP_ASTNode *context_get_proc(Context *context, const char *name) {
- IMP_ASTNode **procdecl = (IMP_ASTNode**)hashmap_get(context->proc_table, name);
- if (procdecl) return *procdecl;
- return NULL;
-}
-
-static void context_set_proc(Context *context, const char *name, IMP_ASTNode *procdecl) {
- hashmap_insert(context->proc_table, name, (void*)procdecl);
-}
-
-Context *context_create(void) {
- Context *context = malloc(sizeof(Context));
- assert(context);
- context->var_table = hashmap_create();
- context->proc_table = hashmap_create();
- return context;
-}
-
-void context_free(Context *context) {
- hashmap_free(context->var_table);
- hashmap_keys_iter_t iter = hashmap_keys_iter_create(context->proc_table);
- const char *key;
- while ((key = hashmap_keys_iter_next(iter)) != NULL) {
- IMP_ASTNode *procdecl = context_get_proc(context, key);
- assert(procdecl);
- imp_ast_free(procdecl);
- }
- hashmap_keys_iter_free(iter);
- hashmap_free(context->proc_table);
- free(context);
-}
-
-int context_get_var(Context *context, const char *name) {
- int *val = (int*)hashmap_get(context->var_table, name);
- if (val) return *val;
- return 0;
-}
-
-void context_set_var(Context *context, const char *name, int val) {
- hashmap_insert(context->var_table, name, (void*)val);
-}
-
-void context_print_var_table(Context *context) {
- hashmap_keys_iter_t iter = hashmap_keys_iter_create(context->var_table);
- const char *key;
- while ((key = hashmap_keys_iter_next(iter)) != NULL) {
- int val = context_get_var(context, key);
- printf("%s = %d\n", key, val);
- }
- hashmap_keys_iter_free(iter);
-}
-
-void context_print_proc_table(Context *context) {
- hashmap_keys_iter_t iter = hashmap_keys_iter_create(context->proc_table);
- const char *key;
- while ((key = hashmap_keys_iter_next(iter)) != NULL) {
- IMP_ASTNode *procdecl = context_get_proc(context, key);
- printf("%s(", key);
- IMP_ASTNodeList *args = procdecl->data.proc_decl.val_args;
- while (args) {
- printf("%s", args->node->data.variable.name);
- args = args->next;
- if (args) printf(", ");
- }
- printf("; ");
- IMP_ASTNodeList *vargs = procdecl->data.proc_decl.var_args;
- while (vargs) {
- printf("%s", vargs->node->data.variable.name);
- vargs = vargs->next;
- if (vargs) printf(", ");
- }
- printf(")\n");
- }
- hashmap_keys_iter_free(iter);
-}
-
-void ast_print(IMP_ASTNode *node, int depth) {
- int indent = depth * 2;
- switch (node->type) {
- case IMP_AST_NT_SKIP: {
- printf("%*sSKIP\n", indent, "");
- break;
- }
- case IMP_AST_NT_ASSIGN: {
- printf("%*sASSIGN %s=", indent, "",
- node->data.assign.var->data.variable.name);
- ast_print(node->data.assign.aexpr, 0);
- printf("\n");
- break;
- }
- case IMP_AST_NT_SEQ: {
- ast_print(node->data.seq.fst_stmt, depth);
- printf("%*sSEQ\n", indent, "");
- ast_print(node->data.seq.snd_stmt, depth);
- break;
- }
- case IMP_AST_NT_IF: {
- printf("%*sIF (", indent, "");
- ast_print(node->data.if_stmt.cond_bexpr, 0);
- printf(")\n");
- ast_print(node->data.if_stmt.then_stmt, depth + 1);
- printf("%*sELSE\n", indent, "");
- ast_print(node->data.if_stmt.else_stmt, depth + 1);
- break;
- }
- case IMP_AST_NT_WHILE: {
- printf("%*sWHILE (", indent, "");
- ast_print(node->data.while_stmt.cond_bexpr, 0);
- printf(")\n");
- ast_print(node->data.while_stmt.body_stmt, depth + 1);
- break;
- }
- case IMP_AST_NT_INT: {
- printf("%d", node->data.integer.val);
- break;
- }
- case IMP_AST_NT_VAR: {
- printf("%s", node->data.variable.name);
- break;
- }
- case IMP_AST_NT_AOP: {
- printf("(");
- ast_print(node->data.arith_op.l_aexpr, 0);
- switch (node->data.arith_op.aopr) {
- case IMP_AST_AOP_ADD: printf(" + "); break;
- case IMP_AST_AOP_SUB: printf(" - "); break;
- case IMP_AST_AOP_MUL: printf(" * "); break;
- default: assert(0);
- }
- ast_print(node->data.arith_op.r_aexpr, 0);
- printf(")");
- break;
- }
- case IMP_AST_NT_BOP: {
- printf("(");
- ast_print(node->data.bool_op.l_bexpr, 0);
- switch (node->data.bool_op.bopr) {
- case IMP_AST_BOP_AND: printf(" && "); break;
- case IMP_AST_BOP_OR: printf(" || "); break;
- default: assert(0);
- }
- ast_print(node->data.bool_op.r_bexpr, 0);
- printf(")");
- break;
- }
- case IMP_AST_NT_NOT: {
- printf("!");
- ast_print(node->data.bool_not.bexpr, 0);
- break;
- }
- case IMP_AST_NT_ROP: {
- printf("(");
- ast_print(node->data.rel_op.l_aexpr, 0);
- switch (node->data.rel_op.ropr) {
- case IMP_AST_ROP_EQ: printf(" == "); break;
- case IMP_AST_ROP_NE: printf(" != "); break;
- case IMP_AST_ROP_LT: printf(" < "); break;
- case IMP_AST_ROP_LE: printf(" <= "); break;
- case IMP_AST_ROP_GT: printf(" > "); break;
- case IMP_AST_ROP_GE: printf(" >= "); break;
- default: assert(0);
- }
- ast_print(node->data.rel_op.r_aexpr, 0);
- printf(")");
- break;
- }
- case IMP_AST_NT_LET: {
- printf("%*sLET %s = ", indent, "", node->data.let_stmt.var->data.variable.name);
- ast_print(node->data.let_stmt.aexpr, 0);
- printf("\n");
- ast_print(node->data.let_stmt.body_stmt, depth + 1);
- break;
- }
- case IMP_AST_NT_PROCDECL: {
- printf("%*sPROC %s(", indent, "", node->data.proc_decl.name);
- IMP_ASTNodeList *args = node->data.proc_decl.val_args;
- while (args) {
- printf("%s", args->node->data.variable.name);
- args = args->next;
- if (args) printf(", ");
- }
- printf("; ");
- IMP_ASTNodeList *vargs = node->data.proc_decl.var_args;
- while (vargs) {
- printf("%s", vargs->node->data.variable.name);
- vargs = vargs->next;
- if (vargs) printf(", ");
- }
- printf(")\n");
- ast_print(node->data.proc_decl.body_stmt, depth + 1);
- break;
- }
- case IMP_AST_NT_PROCCALL: {
- printf("%*sCALL %s(", indent, "", node->data.proc_call.name);
- IMP_ASTNodeList *args = node->data.proc_call.val_args;
- while (args) {
- printf("%s", args->node->data.variable.name);
- args = args->next;
- if (args) printf(", ");
- }
- printf("; ");
- IMP_ASTNodeList *vargs = node->data.proc_call.var_args;
- while (vargs) {
- printf("%s", vargs->node->data.variable.name);
- vargs = vargs->next;
- if (vargs) printf(", ");
- }
- printf(")\n");
- break;
- }
- default: assert(0);
- }
-}
-
-static int eval_aexpr(Context *context, IMP_ASTNode *node) {
+static int eval_aexpr(IMP_InterpreterContext *context, const IMP_ASTNode *node) {
switch (node->type) {
case IMP_AST_NT_INT: return node->data.integer.val;
- case IMP_AST_NT_VAR: return context_get_var(context, node->data.variable.name);
+ case IMP_AST_NT_VAR: return imp_interpreter_context_var_get(context, node->data.variable.name);
case IMP_AST_NT_AOP: {
- int aexp1_val = eval_aexpr(context, node->data.arith_op.l_aexpr);
- int aexp2_val = eval_aexpr(context, node->data.arith_op.r_aexpr);
+ int l_val = eval_aexpr(context, node->data.arith_op.l_aexpr);
+ int r_val = eval_aexpr(context, node->data.arith_op.r_aexpr);
switch (node->data.arith_op.aopr) {
- case IMP_AST_AOP_ADD: return aexp1_val + aexp2_val;
- case IMP_AST_AOP_SUB: return aexp1_val - aexp2_val;
- case IMP_AST_AOP_MUL: return aexp1_val * aexp2_val;
+ case IMP_AST_AOP_ADD: return l_val + r_val;
+ case IMP_AST_AOP_SUB: return l_val - r_val;
+ case IMP_AST_AOP_MUL: return l_val * r_val;
default: assert(0);
}
}
@@ -253,28 +23,28 @@ static int eval_aexpr(Context *context, IMP_ASTNode *node) {
}
}
-static int eval_bexpr(Context *context, IMP_ASTNode *node) {
+static int eval_bexpr(IMP_InterpreterContext *context, const IMP_ASTNode *node) {
switch (node->type) {
case IMP_AST_NT_BOP: {
- int bexp1_val = eval_bexpr(context, node->data.bool_op.l_bexpr);
- int bexp2_val = eval_bexpr(context, node->data.bool_op.r_bexpr);
+ int l_val = eval_bexpr(context, node->data.bool_op.l_bexpr);
+ int r_val = eval_bexpr(context, node->data.bool_op.r_bexpr);
switch (node->data.bool_op.bopr) {
- case IMP_AST_BOP_AND: return bexp1_val && bexp2_val;
- case IMP_AST_BOP_OR: return bexp1_val || bexp2_val;
+ case IMP_AST_BOP_AND: return l_val && r_val;
+ case IMP_AST_BOP_OR: return l_val || r_val;
default: assert(0);
}
}
case IMP_AST_NT_NOT: return !eval_bexpr(context, node->data.bool_not.bexpr);
case IMP_AST_NT_ROP: {
- int aexp1_val = eval_aexpr(context, node->data.rel_op.l_aexpr);
- int aexp2_val = eval_aexpr(context, node->data.rel_op.r_aexpr);
+ int l_val = eval_aexpr(context, node->data.rel_op.l_aexpr);
+ int r_val = eval_aexpr(context, node->data.rel_op.r_aexpr);
switch (node->data.rel_op.ropr) {
- case IMP_AST_ROP_EQ: return aexp1_val == aexp2_val;
- case IMP_AST_ROP_NE: return aexp1_val != aexp2_val;
- case IMP_AST_ROP_LT: return aexp1_val < aexp2_val;
- case IMP_AST_ROP_LE: return aexp1_val <= aexp2_val;
- case IMP_AST_ROP_GT: return aexp1_val > aexp2_val;
- case IMP_AST_ROP_GE: return aexp1_val >= aexp2_val;
+ case IMP_AST_ROP_EQ: return l_val == r_val;
+ case IMP_AST_ROP_NE: return l_val != r_val;
+ case IMP_AST_ROP_LT: return l_val < r_val;
+ case IMP_AST_ROP_LE: return l_val <= r_val;
+ case IMP_AST_ROP_GT: return l_val > r_val;
+ case IMP_AST_ROP_GE: return l_val >= r_val;
default: assert(0);
}
}
@@ -282,155 +52,98 @@ static int eval_bexpr(Context *context, IMP_ASTNode *node) {
}
}
-static int interp_proccall(Context *context, IMP_ASTNode *node) {
+static int interpret_proccall(IMP_InterpreterContext *context, const IMP_ASTNode *node) {
const char *name = node->data.proc_call.name;
- IMP_ASTNode *procdecl = context_get_proc(context, name);
+ const IMP_ASTNode *procdecl = imp_interpreter_context_proc_get(context, name);
if (!procdecl) {
fprintf(stderr, "Error: procedure %s not defined\n", name);
return -1;
}
- IMP_ASTNodeList *caller_args = node->data.proc_call.val_args;
- IMP_ASTNodeList *callee_args = procdecl->data.proc_decl.val_args;
- Context *proc_context = context_create();
- hashmap_keys_iter_t iter = hashmap_keys_iter_create(context->proc_table);
- const char *key;
- while ((key = hashmap_keys_iter_next(iter)) != NULL) {
- IMP_ASTNode *proc = context_get_proc(context, key);
- context_set_proc(proc_context, key, imp_ast_clone(proc));
- }
- hashmap_keys_iter_free(iter);
- while (caller_args && callee_args) {
- const char *caller_arg_name = caller_args->node->data.variable.name;
- const char *callee_arg_name = callee_args->node->data.variable.name;
- context_set_var(proc_context, callee_arg_name, context_get_var(context, caller_arg_name));
- caller_args = caller_args->next;
- callee_args = callee_args->next;
- }
- if (caller_args || callee_args) {
+ IMP_InterpreterContext *proc_context = imp_interpreter_context_create();
+ IMP_InterpreterContextProcIter *proc_iter = imp_interpreter_context_proc_iter_create(context);
+ const IMP_InterpreterContextProcTableEntry *proc_entry;
+ while ((proc_entry = imp_interpreter_context_proc_iter_next(proc_iter))) {
+ imp_interpreter_context_proc_set(proc_context, proc_entry->key, proc_entry->value);
+ }
+ imp_interpreter_context_proc_iter_destroy(proc_iter);
+ IMP_ASTNodeList *caller_val_args = node->data.proc_call.val_args;
+ IMP_ASTNodeList *callee_val_args = procdecl->data.proc_decl.val_args;
+ while (caller_val_args && callee_val_args) {
+ const char *caller_arg_name = caller_val_args->node->data.variable.name;
+ const char *callee_arg_name = callee_val_args->node->data.variable.name;
+ imp_interpreter_context_var_set(proc_context, callee_arg_name, imp_interpreter_context_var_get(context, caller_arg_name));
+ caller_val_args = caller_val_args->next;
+ callee_val_args = callee_val_args->next;
+ }
+ if (caller_val_args || callee_val_args) {
fprintf(stderr, "Error: procedure %s called with wrong number of value arguments\n", name);
- context_free(proc_context);
+ imp_interpreter_context_destroy(proc_context);
return -1;
}
- if (interp_ast(proc_context, procdecl->data.proc_decl.body_stmt)) {
- context_free(proc_context);
+ if (imp_interpreter_interpret_ast(proc_context, procdecl->data.proc_decl.body_stmt)) {
+ imp_interpreter_context_destroy(proc_context);
return -1;
}
- IMP_ASTNodeList *caller_vargs = node->data.proc_call.var_args;
- IMP_ASTNodeList *callee_vargs = procdecl->data.proc_decl.var_args;
- while (caller_vargs && callee_vargs) {
- const char *caller_varg_name = caller_vargs->node->data.variable.name;
- const char *callee_varg_name = callee_vargs->node->data.variable.name;
- context_set_var(context, caller_varg_name, context_get_var(proc_context, callee_varg_name));
- caller_vargs = caller_vargs->next;
- callee_vargs = callee_vargs->next;
+ IMP_ASTNodeList *caller_var_args = node->data.proc_call.var_args;
+ IMP_ASTNodeList *callee_var_args = procdecl->data.proc_decl.var_args;
+ while (caller_var_args && callee_var_args) {
+ const char *caller_varg_name = caller_var_args->node->data.variable.name;
+ const char *callee_varg_name = callee_var_args->node->data.variable.name;
+ imp_interpreter_context_var_set(context, caller_varg_name, imp_interpreter_context_var_get(proc_context, callee_varg_name));
+ caller_var_args = caller_var_args->next;
+ callee_var_args = callee_var_args->next;
}
- if (caller_vargs || callee_vargs) {
+ if (caller_var_args || callee_var_args) {
fprintf(stderr, "Error: procedure %s called with wrong number of variable arguments\n", name);
- context_free(proc_context);
+ imp_interpreter_context_destroy(proc_context);
return -1;
}
- context_free(proc_context);
+ imp_interpreter_context_destroy(proc_context);
return 0;
}
-int interp_ast(Context *context, IMP_ASTNode *node) {
+int imp_interpreter_interpret_ast(IMP_InterpreterContext *context, const IMP_ASTNode *node) {
switch (node->type) {
case IMP_AST_NT_SKIP: return 0;
case IMP_AST_NT_ASSIGN: {
const char *name = node->data.assign.var->data.variable.name;
int val = eval_aexpr(context, node->data.assign.aexpr);
- context_set_var(context, name, val);
+ imp_interpreter_context_var_set(context, name, val);
return 0;
}
case IMP_AST_NT_SEQ:
- if (interp_ast(context, node->data.seq.fst_stmt)) return -1;
- if (interp_ast(context, node->data.seq.snd_stmt)) return -1;
+ if (imp_interpreter_interpret_ast(context, node->data.seq.fst_stmt)) return -1;
+ if (imp_interpreter_interpret_ast(context, node->data.seq.snd_stmt)) return -1;
return 0;
case IMP_AST_NT_IF:
- if (eval_bexpr(context, node->data.if_stmt.cond_bexpr)) return interp_ast(context, node->data.if_stmt.then_stmt);
- else return interp_ast(context, node->data.if_stmt.else_stmt);
+ if (eval_bexpr(context, node->data.if_stmt.cond_bexpr)) return imp_interpreter_interpret_ast(context, node->data.if_stmt.then_stmt);
+ else return imp_interpreter_interpret_ast(context, node->data.if_stmt.else_stmt);
case IMP_AST_NT_WHILE:
while (eval_bexpr(context, node->data.while_stmt.cond_bexpr)) {
- if (interp_ast(context, node->data.while_stmt.body_stmt)) return -1;
+ if (imp_interpreter_interpret_ast(context, node->data.while_stmt.body_stmt)) return -1;
}
return 0;
case IMP_AST_NT_LET: {
const char *name = node->data.let_stmt.var->data.variable.name;
- int old_val = context_get_var(context, name);
+ int old_val = imp_interpreter_context_var_get(context, name);
int new_val = eval_aexpr(context, node->data.let_stmt.aexpr);
- context_set_var(context, name, new_val);
- int ret = interp_ast(context, node->data.let_stmt.body_stmt);
- context_set_var(context, name, old_val);
+ imp_interpreter_context_var_set(context, name, new_val);
+ int ret = imp_interpreter_interpret_ast(context, node->data.let_stmt.body_stmt);
+ imp_interpreter_context_var_set(context, name, old_val);
return ret;
}
case IMP_AST_NT_PROCDECL: {
const char *name = node->data.proc_decl.name;
- IMP_ASTNode *procdecl_old = context_get_proc(context, name);
- if (procdecl_old) {
+ if (imp_interpreter_context_proc_get(context, name)) {
fprintf(stderr, "Error: procedure %s already defined\n", name);
return -1;
}
- IMP_ASTNode *procdecl = imp_ast_clone(node);
- context_set_proc(context, name, procdecl);
+ imp_interpreter_context_proc_set(context, name, node);
return 0;
}
case IMP_AST_NT_PROCCALL: {
- return interp_proccall(context, node);
+ return interpret_proccall(context, node);
}
default: assert(0);
}
-}
-
-int interp_file (Context *context, const char *path) {
- yyin = fopen(path, "r");
- if (!yyin) {
- return -1;
- }
- yyrestart(yyin);
- if (yyparse()) {
- imp_ast_free(ast_root);
- fclose(yyin);
- return -1;
- }
- if (interp_ast(context, ast_root)) {
- imp_ast_free(ast_root);
- fclose(yyin);
- return -1;
- }
- imp_ast_free(ast_root);
- fclose(yyin);
- return 0;
-}
-
-int interp_str (Context *context, const char *str) {
- YY_BUFFER_STATE buf = yy_scan_string(str);
- if (yyparse()) {
- imp_ast_free(ast_root);
- yy_delete_buffer(buf);
- return -1;
- }
- if (interp_ast(context, ast_root)) {
- imp_ast_free(ast_root);
- yy_delete_buffer(buf);
- return -1;
- }
- yy_delete_buffer(buf);
- return 0;
-}
-
-int print_ast_file (const char *path) {
- yyin = fopen(path, "r");
- if (!yyin) {
- return -1;
- }
- yyrestart(yyin);
- if (yyparse()) {
- imp_ast_free(ast_root);
- fclose(yyin);
- return -1;
- }
- ast_print(ast_root, 0);
- imp_ast_free(ast_root);
- fclose(yyin);
- return 0;
} \ No newline at end of file