aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast.c56
-rw-r--r--src/driver.c260
-rw-r--r--src/hashmap.c160
-rw-r--r--src/interpreter.c421
-rw-r--r--src/interpreter_context.c123
-rw-r--r--src/main.c45
-rw-r--r--src/repl.c28
7 files changed, 505 insertions, 588 deletions
diff --git a/src/ast.c b/src/ast.c
index 03e6100..9c13d79 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -170,27 +170,27 @@ IMP_ASTNode *imp_ast_clone(const IMP_ASTNode *node) {
}
}
-void imp_ast_free(IMP_ASTNode *node) {
+void imp_ast_destroy(IMP_ASTNode *node) {
if (!node) return;
switch (node->type) {
case IMP_AST_NT_SKIP:
break;
case IMP_AST_NT_ASSIGN:
- imp_ast_free(node->data.assign.var);
- imp_ast_free(node->data.assign.aexpr);
+ imp_ast_destroy(node->data.assign.var);
+ imp_ast_destroy(node->data.assign.aexpr);
break;
case IMP_AST_NT_SEQ:
- imp_ast_free(node->data.seq.fst_stmt);
- imp_ast_free(node->data.seq.snd_stmt);
+ imp_ast_destroy(node->data.seq.fst_stmt);
+ imp_ast_destroy(node->data.seq.snd_stmt);
break;
case IMP_AST_NT_IF:
- imp_ast_free(node->data.if_stmt.cond_bexpr);
- imp_ast_free(node->data.if_stmt.then_stmt);
- imp_ast_free(node->data.if_stmt.else_stmt);
+ imp_ast_destroy(node->data.if_stmt.cond_bexpr);
+ imp_ast_destroy(node->data.if_stmt.then_stmt);
+ imp_ast_destroy(node->data.if_stmt.else_stmt);
break;
case IMP_AST_NT_WHILE:
- imp_ast_free(node->data.while_stmt.cond_bexpr);
- imp_ast_free(node->data.while_stmt.body_stmt);
+ imp_ast_destroy(node->data.while_stmt.cond_bexpr);
+ imp_ast_destroy(node->data.while_stmt.body_stmt);
break;
case IMP_AST_NT_INT:
break;
@@ -198,35 +198,35 @@ void imp_ast_free(IMP_ASTNode *node) {
free(node->data.variable.name);
break;
case IMP_AST_NT_AOP:
- imp_ast_free(node->data.arith_op.l_aexpr);
- imp_ast_free(node->data.arith_op.r_aexpr);
+ imp_ast_destroy(node->data.arith_op.l_aexpr);
+ imp_ast_destroy(node->data.arith_op.r_aexpr);
break;
case IMP_AST_NT_BOP:
- imp_ast_free(node->data.bool_op.l_bexpr);
- imp_ast_free(node->data.bool_op.r_bexpr);
+ imp_ast_destroy(node->data.bool_op.l_bexpr);
+ imp_ast_destroy(node->data.bool_op.r_bexpr);
break;
case IMP_AST_NT_ROP:
- imp_ast_free(node->data.rel_op.l_aexpr);
- imp_ast_free(node->data.rel_op.r_aexpr);
+ imp_ast_destroy(node->data.rel_op.l_aexpr);
+ imp_ast_destroy(node->data.rel_op.r_aexpr);
break;
case IMP_AST_NT_NOT:
- imp_ast_free(node->data.bool_not.bexpr);
+ imp_ast_destroy(node->data.bool_not.bexpr);
break;
case IMP_AST_NT_LET:
- imp_ast_free(node->data.let_stmt.var);
- imp_ast_free(node->data.let_stmt.aexpr);
- imp_ast_free(node->data.let_stmt.body_stmt);
+ imp_ast_destroy(node->data.let_stmt.var);
+ imp_ast_destroy(node->data.let_stmt.aexpr);
+ imp_ast_destroy(node->data.let_stmt.body_stmt);
break;
case IMP_AST_NT_PROCDECL:
free(node->data.proc_decl.name);
- imp_ast_list_free(node->data.proc_decl.val_args);
- imp_ast_list_free(node->data.proc_decl.var_args);
- imp_ast_free(node->data.proc_decl.body_stmt);
+ imp_ast_list_destroy(node->data.proc_decl.val_args);
+ imp_ast_list_destroy(node->data.proc_decl.var_args);
+ imp_ast_destroy(node->data.proc_decl.body_stmt);
break;
case IMP_AST_NT_PROCCALL:
free(node->data.proc_call.name);
- imp_ast_list_free(node->data.proc_call.val_args);
- imp_ast_list_free(node->data.proc_call.var_args);
+ imp_ast_list_destroy(node->data.proc_call.val_args);
+ imp_ast_list_destroy(node->data.proc_call.var_args);
break;
default: assert(0 && "Unknown AST node type");
}
@@ -241,9 +241,9 @@ IMP_ASTNodeList *imp_ast_list(IMP_ASTNode *node, IMP_ASTNodeList *list) {
return new_list;
}
-void imp_ast_list_free(IMP_ASTNodeList *list) {
+void imp_ast_list_destroy(IMP_ASTNodeList *list) {
if (!list) return;
- imp_ast_free(list->node);
- imp_ast_list_free(list->next);
+ imp_ast_destroy(list->node);
+ imp_ast_list_destroy(list->next);
free(list);
} \ No newline at end of file
diff --git a/src/driver.c b/src/driver.c
index 441ee40..5f6037d 100644
--- a/src/driver.c
+++ b/src/driver.c
@@ -1,44 +1,238 @@
-#include <stdio.h>
+#include "driver.h"
+
#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
+#include <stdio.h>
+#include <assert.h>
+#include "ast.h"
#include "interpreter.h"
-#include "repl.h"
-static int interpret_file(const char *path) {
- context_t context = context_create();
- if (interp_file(context, path)) {
- fprintf(stderr, "Error interpreting file: %s\n", path);
- context_free(context);
+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);
+
+int imp_driver_interpret_file (IMP_InterpreterContext *context, const char *path) {
+ yyin = fopen(path, "r");
+ if (!yyin) return -1;
+ yyrestart(yyin);
+ if (yyparse()) {
+ imp_ast_destroy(ast_root);
+ fclose(yyin);
+ return -1;
+ }
+ if (imp_interpreter_interpret_ast(context, ast_root)) {
+ imp_ast_destroy(ast_root);
+ fclose(yyin);
return -1;
}
- context_print_var_table(context);
- context_free(context);
+ imp_ast_destroy(ast_root);
+ fclose(yyin);
return 0;
}
-int main(int argc, char **argv) {
- int opt;
- while ((opt = getopt(argc, argv, "i:a:h")) != -1) {
- switch (opt) {
- case 'i':
- return interpret_file(optarg) ? EXIT_FAILURE : EXIT_SUCCESS;
- case 'a':
- return print_ast_file(optarg) ? EXIT_FAILURE : EXIT_SUCCESS;
- case 'h':
- default:
- fprintf(stderr,
- "Usage: %s [ARGS]\n"
- " (no args) start REPL\n"
- " -i <program.imp> interpret program\n"
- " -a <program.imp> print ast\n"
- " -h print this message\n",
- argv[0]);
- return (opt == 'h') ? EXIT_SUCCESS : EXIT_FAILURE;
- }
- }
- repl();
- return EXIT_SUCCESS;
+int imp_driver_interpret_str (IMP_InterpreterContext *context, const char *str) {
+ YY_BUFFER_STATE buf = yy_scan_string(str);
+ if (yyparse()) {
+ imp_ast_destroy(ast_root);
+ yy_delete_buffer(buf);
+ return -1;
+ }
+ if (imp_interpreter_interpret_ast(context, ast_root)) {
+ imp_ast_destroy(ast_root);
+ yy_delete_buffer(buf);
+ return -1;
+ }
+ yy_delete_buffer(buf);
+ return 0;
+}
+
+static 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);
+ }
+}
+
+int imp_driver_print_ast_file (const char *path) {
+ yyin = fopen(path, "r");
+ if (!yyin) return -1;
+ yyrestart(yyin);
+ if (yyparse()) {
+ imp_ast_destroy(ast_root);
+ fclose(yyin);
+ return -1;
+ }
+ ast_print(ast_root, 0);
+ imp_ast_destroy(ast_root);
+ fclose(yyin);
+ return 0;
+}
+
+void imp_driver_print_var_table(IMP_InterpreterContext *context) {
+ IMP_InterpreterContextVarIter *iter = imp_interpreter_context_var_iter_create(context);
+ const IMP_InterpreterContextVarTableEntry *var_entry;
+ while ((var_entry = imp_interpreter_context_var_iter_next(iter))) {
+ printf("%s = %d\n", var_entry->key, var_entry->value);
+ }
+ imp_interpreter_context_var_iter_destroy(iter);
+}
+
+void imp_driver_print_proc_table(IMP_InterpreterContext *context) {
+ IMP_InterpreterContextProcIter *iter = imp_interpreter_context_proc_iter_create(context);
+ const IMP_InterpreterContextProcTableEntry *proc_entry;
+ while ((proc_entry = imp_interpreter_context_proc_iter_next(iter))) {
+ const IMP_ASTNode *procdecl = proc_entry->value;
+ printf("%s(", proc_entry->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");
+ }
+ imp_interpreter_context_proc_iter_destroy(iter);
} \ No newline at end of file
diff --git a/src/hashmap.c b/src/hashmap.c
deleted file mode 100644
index 89d0106..0000000
--- a/src/hashmap.c
+++ /dev/null
@@ -1,160 +0,0 @@
-#include "hashmap.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-
-#define INITIAL_SIZE (16)
-#define LOAD_FACTOR_THRESHOLD (0.75)
-
-
-typedef struct Pair {
- char *key;
- void *element;
- struct Pair *next;
-} Pair;
-
-typedef struct HashMap {
- Pair **table;
- size_t size;
- size_t count;
-} HashMap;
-
-typedef struct HashMapKeysIter {
- HashMap *map;
- size_t bucket_index;
- Pair *current;
-} HashMapKeysIter;
-
-
-static unsigned int hash(const char *key, size_t size) {
- unsigned int hash_value = 0;
- while (*key) hash_value = (hash_value * 31) + *key++;
- return hash_value % size;
-}
-
-static void resize(HashMap *map) {
- size_t new_size = map->size * 2;
- Pair **new_table = (Pair**)calloc(new_size, sizeof(Pair*));
- assert(new_table);
- for (size_t i = 0; i < map->size; ++i) {
- Pair *pair = map->table[i];
- while (pair) {
- unsigned int index = hash(pair->key, new_size);
- Pair *next = pair->next;
- pair->next = new_table[index];
- new_table[index] = pair;
- pair = next;
- }
- }
-
- free(map->table);
- map->table = new_table;
- map->size = new_size;
-}
-
-HashMap *hashmap_create(void) {
- HashMap *map = (HashMap*)malloc(sizeof(HashMap));
- assert(map);
- map->size = INITIAL_SIZE;
- map->count = 0;
- map->table = (Pair**)calloc(map->size, sizeof(Pair*));
- assert(map->table);
- return map;
-}
-
-void hashmap_insert(HashMap *map, const char *key, void *element) {
- void **old_value = hashmap_get(map, key);
- if (old_value) {
- *old_value = element;
- return;
- }
- if ((float)map->count / map->size > LOAD_FACTOR_THRESHOLD) resize(map);
- unsigned int index = hash(key, map->size);
- Pair *new_pair = (Pair*)malloc(sizeof(Pair));
- assert(new_pair);
- new_pair->key = strdup(key);
- assert(new_pair->key);
- new_pair->element = element;
- new_pair->next = map->table[index];
- map->table[index] = new_pair;
- map->count++;
-}
-
-void **hashmap_get(HashMap *map, const char *key) {
- unsigned int index = hash(key, map->size);
- Pair *pair = map->table[index];
- while (pair) {
- if (strcmp(pair->key, key) == 0) return &pair->element;
- pair = pair->next;
- }
- return NULL;
-}
-
-int hashmap_delete(HashMap *map, const char *key) {
- unsigned int index = hash(key, map->size);
- Pair *pair = map->table[index];
- Pair *prev = NULL;
- while (pair) {
- if (strcmp(pair->key, key) == 0) {
- if (prev) prev->next = pair->next;
- else map->table[index] = pair->next;
- free(pair->key);
- free(pair);
- map->count--;
- return 0;
- }
- prev = pair;
- pair = pair->next;
- }
- return -1;
-}
-
-void hashmap_free(HashMap *map) {
- for (size_t i = 0; i < map->size; ++i) {
- Pair *pair = map->table[i];
- while (pair) {
- Pair *temp = pair;
- pair = pair->next;
- free(temp->key);
- free(temp);
- }
- }
- free(map->table);
- free(map);
-}
-
-HashMapKeysIter *hashmap_keys_iter_create(HashMap *map) {
- HashMapKeysIter *iter = (HashMapKeysIter*)malloc(sizeof(HashMapKeysIter));
- assert(iter);
- iter->map = map;
- iter->bucket_index = 0;
- iter->current = NULL;
- while (iter->bucket_index < map->size && map->table[iter->bucket_index] == NULL) {
- iter->bucket_index++;
- }
- if (iter->bucket_index < map->size) {
- iter->current = map->table[iter->bucket_index];
- }
- return iter;
-}
-
-const char *hashmap_keys_iter_next(HashMapKeysIter *iter) {
- if (!iter->current) return NULL;
- const char *key = iter->current->key;
- if (iter->current->next) {
- iter->current = iter->current->next;
- } else {
- iter->bucket_index++;
- while (iter->bucket_index < iter->map->size && iter->map->table[iter->bucket_index] == NULL) {
- iter->bucket_index++;
- }
- iter->current = (iter->bucket_index < iter->map->size) ? iter->map->table[iter->bucket_index] : NULL;
- }
- return key;
-}
-
-void hashmap_keys_iter_free(HashMapKeysIter *iter) {
- free(iter);
-} \ No newline at end of file
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
diff --git a/src/interpreter_context.c b/src/interpreter_context.c
new file mode 100644
index 0000000..488f872
--- /dev/null
+++ b/src/interpreter_context.c
@@ -0,0 +1,123 @@
+#include "interpreter_context.h"
+
+#define STB_DS_IMPLEMENTATION
+#include "3rdparty/stb_ds/stb_ds.h"
+
+
+struct IMP_InterpreterContext {
+ IMP_InterpreterContextVarTableEntry *var_table;
+ IMP_InterpreterContextProcTableEntry *proc_table;
+};
+
+struct IMP_InterpreterContextVarIter {
+ IMP_InterpreterContextVarTableEntry *var_table;
+ ptrdiff_t index;
+ ptrdiff_t len;
+};
+
+struct IMP_InterpreterContextProcIter {
+ IMP_InterpreterContextProcTableEntry *proc_table;
+ ptrdiff_t index;
+ ptrdiff_t len;
+};
+
+IMP_InterpreterContext *imp_interpreter_context_create(void) {
+ IMP_InterpreterContext *context = malloc(sizeof(IMP_InterpreterContext));
+ assert(context && "Memory allocation failed");
+ context->var_table = NULL;
+ context->proc_table = NULL;
+ return context;
+}
+
+void imp_interpreter_context_destroy(IMP_InterpreterContext *context) {
+ ptrdiff_t len = shlen(context->var_table);
+ for (ptrdiff_t i = 0; i < len; ++i) free((char*)context->var_table[i].key);
+ shfree(context->var_table);
+}
+
+int imp_interpreter_context_var_get(IMP_InterpreterContext *context, const char *name) {
+ ptrdiff_t index = shgeti(context->var_table, name);
+ if (index < 0) return 0;
+ return context->var_table[index].value;
+}
+
+void imp_interpreter_context_var_set(IMP_InterpreterContext *context, const char *name, int value) {
+ ptrdiff_t index = shgeti(context->var_table, name);
+ if (index < 0) {
+ if (value == 0) return;
+ const char* key = strdup(name);
+ assert(key && "Memory allocation failed");
+ shput(context->var_table, key, value);
+ } else {
+ if (value == 0) {
+ const char *key = context->var_table[index].key;
+ shdel(context->var_table, name);
+ free((char*)key);
+ return;
+ }
+ context->var_table[index].value = value;
+ }
+}
+
+const IMP_ASTNode *imp_interpreter_context_proc_get(IMP_InterpreterContext *context, const char *name) {
+ ptrdiff_t index = shgeti(context->proc_table, name);
+ if (index < 0) return NULL;
+ return context->proc_table[index].value;
+}
+
+void imp_interpreter_context_proc_set(IMP_InterpreterContext *context, const char *name, const IMP_ASTNode *proc) {
+ ptrdiff_t index = shgeti(context->proc_table, name);
+ proc = imp_ast_clone(proc);
+ if (proc) assert(proc->type == IMP_AST_NT_PROCDECL);
+ if (index < 0) {
+ if (proc == NULL) return;
+ const char* key = strdup(name);
+ assert(key && "Memory allocation failed");
+ shput(context->proc_table, key, proc);
+ } else {
+ imp_ast_destroy((IMP_ASTNode*)context->proc_table[index].value);
+ if (proc == NULL) {
+ const char *key = context->proc_table[index].key;
+ shdel(context->proc_table, name);
+ free((char*)key);
+ return;
+ }
+ context->proc_table[index].value = proc;
+ }
+}
+
+IMP_InterpreterContextVarIter *imp_interpreter_context_var_iter_create(IMP_InterpreterContext *context) {
+ IMP_InterpreterContextVarIter *iter = malloc(sizeof(IMP_InterpreterContextVarIter));
+ assert(iter && "Memory allocation failed");
+ iter->var_table = context->var_table;
+ iter->index = 0;
+ iter->len = shlen(context->var_table);
+ return iter;
+}
+
+void imp_interpreter_context_var_iter_destroy(IMP_InterpreterContextVarIter *iter) {
+ free(iter);
+}
+
+IMP_InterpreterContextVarTableEntry *imp_interpreter_context_var_iter_next(IMP_InterpreterContextVarIter *iter) {
+ if (iter->index >= iter->len) return NULL;
+ return &iter->var_table[iter->index++];
+}
+
+IMP_InterpreterContextProcIter *imp_interpreter_context_proc_iter_create(IMP_InterpreterContext *context) {
+ IMP_InterpreterContextProcIter *iter = malloc(sizeof(IMP_InterpreterContextProcIter));
+ assert(iter && "Memory allocation failed");
+ iter->proc_table = context->proc_table;
+ iter->index = 0;
+ iter->len = shlen(context->proc_table);
+ return iter;
+}
+
+void imp_interpreter_context_proc_iter_destroy(IMP_InterpreterContextProcIter *iter) {
+ free(iter);
+}
+
+IMP_InterpreterContextProcTableEntry *imp_interpreter_context_proc_iter_next(IMP_InterpreterContextProcIter *iter) {
+ if (iter->index >= iter->len) return NULL;
+ return &iter->proc_table[iter->index++];
+} \ No newline at end of file
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..5ef854d
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "interpreter_context.h"
+#include "driver.h"
+#include "repl.h"
+
+
+static int interpret_file(const char *path) {
+ IMP_InterpreterContext *context = imp_interpreter_context_create();
+ if (imp_driver_interpret_file(context, path)) {
+ fprintf(stderr, "Error interpreting file: %s\n", path);
+ imp_interpreter_context_destroy(context);
+ return -1;
+ }
+ imp_driver_print_var_table(context);
+ imp_interpreter_context_destroy(context);
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ int opt;
+ while ((opt = getopt(argc, argv, "i:a:h")) != -1) {
+ switch (opt) {
+ case 'i':
+ return interpret_file(optarg) ? EXIT_FAILURE : EXIT_SUCCESS;
+ case 'a':
+ return imp_driver_print_ast_file(optarg) ? EXIT_FAILURE : EXIT_SUCCESS;
+ case 'h':
+ default:
+ fprintf(stderr,
+ "Usage: %s [ARGS]\n"
+ " (no args) start REPL\n"
+ " -i <program.imp> interpret program\n"
+ " -a <program.imp> print ast\n"
+ " -h print this message\n",
+ argv[0]);
+ return (opt == 'h') ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+ }
+ imp_repl();
+ return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/src/repl.c b/src/repl.c
index 199c110..b553aec 100644
--- a/src/repl.c
+++ b/src/repl.c
@@ -8,7 +8,8 @@
#include <readline/readline.h>
#include <readline/history.h>
-#include "interpreter.h"
+#include "interpreter_context.h"
+#include "driver.h"
static void print_help(void) {
@@ -31,7 +32,7 @@ static int is_valid_identifier(const char *var) {
return 1;
}
-static void repl_exec_command(context_t context, char *command) {
+static void repl_exec_command(IMP_InterpreterContext *context, char *command) {
char *cmd = strtok(command, " \t");
if (strcmp(cmd, "%quit") == 0) {
exit(EXIT_SUCCESS);
@@ -40,7 +41,8 @@ static void repl_exec_command(context_t context, char *command) {
} else if (strcmp(cmd, "%run") == 0) {
char *file = strtok(NULL, " \t");
if (file) {
- if (!interp_file(context, file)) context_print_var_table(context);
+ if (!imp_driver_interpret_file(context, file)) imp_driver_print_var_table(context);
+ else fprintf(stderr, "Error interpreting file: %s\n", file);
} else {
fprintf(stderr, "Usage: %%run <path/to/file.imp>\n");
}
@@ -49,7 +51,7 @@ static void repl_exec_command(context_t context, char *command) {
char *val = strtok(NULL, " \t");
if (var && val) {
if (is_valid_identifier(var)) {
- context_set_var(context, var, atoi(val));
+ imp_interpreter_context_var_set(context, var, atoi(val));
} else {
fprintf(stderr, "Invalid variable name: %s\n", var);
}
@@ -58,28 +60,28 @@ static void repl_exec_command(context_t context, char *command) {
char *var = strtok(NULL, " \t");
if (var) {
if (is_valid_identifier(var)) {
- printf("%s = %d\n", var, context_get_var(context, var));
+ printf("%s = %d\n", var, imp_interpreter_context_var_get(context, var));
} else {
fprintf(stderr, "Invalid variable name: %s\n", var);
}
- } else context_print_var_table(context);
+ } else imp_driver_print_var_table(context);
} else if (strcmp(cmd, "%procedures") == 0) {
- context_print_proc_table(context);
+ imp_driver_print_proc_table(context);
} else {
fprintf(stderr, "Unknown command: %s\n", cmd);
}
}
-static void repl_exec_statement(context_t context, const char *statement) {
- if (interp_str(context, statement)) {
+static void repl_exec_statement(IMP_InterpreterContext *context, const char *statement) {
+ if (imp_driver_interpret_str(context, statement)) {
fprintf(stderr, "Error interpreting statement: %s\n", statement);
return;
}
- context_print_var_table(context);
+ imp_driver_print_var_table(context);
}
-void repl(void) {
- context_t context = context_create();
+void imp_repl(void) {
+ IMP_InterpreterContext *context = imp_interpreter_context_create();
char *line;
print_help();
@@ -91,5 +93,5 @@ void repl(void) {
}
printf("\n");
- context_free(context);
+ imp_interpreter_context_destroy(context);
} \ No newline at end of file