aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFlavian Kaufmann <flavian@flaviankaufmann.ch>2025-05-21 14:05:27 +0200
committerFlavian Kaufmann <flavian@flaviankaufmann.ch>2025-05-21 14:05:27 +0200
commit8b6acc85633520f109d348c5e46c8a89521b3932 (patch)
tree1196ec5c493fd57937e7c84ca6ffb9f2d511b264 /src
parent442eba08dba74c3254a8d089ca1961147e59972b (diff)
downloadimp-8b6acc85633520f109d348c5e46c8a89521b3932.tar.gz
imp-8b6acc85633520f109d348c5e46c8a89521b3932.zip
procedures
Diffstat (limited to 'src')
-rw-r--r--src/ast.c97
-rw-r--r--src/driver.c13
-rw-r--r--src/hashmap.c (renamed from src/hash_map.c)61
-rw-r--r--src/interpreter.c235
-rw-r--r--src/lexer.l3
-rw-r--r--src/parser.y33
-rw-r--r--src/repl.c28
7 files changed, 349 insertions, 121 deletions
diff --git a/src/ast.c b/src/ast.c
index 66e76ea..ba8dc9f 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -1,5 +1,5 @@
#include "ast.h"
-#include <stdio.h>
+
#include <stdlib.h>
#include <string.h>
#include <assert.h>
@@ -96,6 +96,39 @@ ASTNode *ast_let(ASTNode *var, ASTNode *aexp, ASTNode *stm) {
return node;
}
+ASTNode *ast_procdecl(const char *name, ASTNodeList *args, ASTNodeList *vargs, ASTNode *stm) {
+ ASTNode *node = new_node(NT_PROCDECL);
+ node->u.d_procdecl.name = strdup(name);
+ assert(node->u.d_procdecl.name);
+ node->u.d_procdecl.args = args;
+ node->u.d_procdecl.vargs = vargs;
+ node->u.d_procdecl.stm = stm;
+ return node;
+}
+
+ASTNode *ast_proccall(const char *name, ASTNodeList *args, ASTNodeList *vargs) {
+ ASTNode *node = new_node(NT_PROCCALL);
+ node->u.d_proccall.name = strdup(name);
+ assert(node->u.d_proccall.name);
+ node->u.d_proccall.args = args;
+ node->u.d_proccall.vargs = vargs;
+ return node;
+}
+
+ASTNodeList *ast_node_list(ASTNode *node, ASTNodeList *list) {
+ ASTNodeList *new_list = malloc(sizeof(ASTNodeList));
+ assert(new_list);
+ new_list->node = node;
+ new_list->next = list;
+ return new_list;
+}
+
+static void ast_free_node_list(ASTNodeList *list) {
+ if (!list) return;
+ ast_free(list->node);
+ ast_free_node_list(list->next);
+ free(list);
+}
void ast_free(ASTNode *node) {
if (!node) return;
@@ -144,6 +177,68 @@ void ast_free(ASTNode *node) {
ast_free(node->u.d_let.aexp);
ast_free(node->u.d_let.stm);
break;
+ case NT_PROCDECL:
+ free(node->u.d_procdecl.name);
+ ast_free_node_list(node->u.d_procdecl.args);
+ ast_free_node_list(node->u.d_procdecl.vargs);
+ ast_free(node->u.d_procdecl.stm);
+ break;
+ case NT_PROCCALL:
+ free(node->u.d_proccall.name);
+ ast_free_node_list(node->u.d_proccall.args);
+ ast_free_node_list(node->u.d_proccall.vargs);
+ break;
+ default: assert(0);
}
free(node);
+}
+
+static ASTNodeList *ast_node_list_clone(ASTNodeList *list) {
+ if (!list) return NULL;
+ return ast_node_list(ast_clone(list->node), ast_node_list_clone(list->next));
+}
+
+ASTNode *ast_clone(ASTNode *node) {
+ if (!node) return NULL;
+ switch (node->type) {
+ case NT_SKIP: return ast_skip();
+ case NT_ASSIGN: return ast_assign(ast_clone(node->u.d_assign.var), ast_clone(node->u.d_assign.aexp));
+ case NT_SEQ: return ast_seq(ast_clone(node->u.d_seq.stm1), ast_clone(node->u.d_seq.stm2));
+ case NT_IF: return ast_if(
+ ast_clone(node->u.d_if.bexp),
+ ast_clone(node->u.d_if.stm1),
+ ast_clone(node->u.d_if.stm2));
+ case NT_WHILE: return ast_while(
+ ast_clone(node->u.d_while.bexp),
+ ast_clone(node->u.d_while.stm));
+ case NT_INT: return ast_int(node->u.d_int.val);
+ case NT_VAR: return ast_var(node->u.d_var.name);
+ case NT_AOP: return ast_aop(
+ node->u.d_aop.aop,
+ ast_clone(node->u.d_aop.aexp1),
+ ast_clone(node->u.d_aop.aexp2));
+ case NT_BOP: return ast_bop(
+ node->u.d_bop.bop,
+ ast_clone(node->u.d_bop.bexp1),
+ ast_clone(node->u.d_bop.bexp2));
+ case NT_NOT: return ast_not(ast_clone(node->u.d_not.bexp));
+ case NT_ROP: return ast_rop(
+ node->u.d_rop.rop,
+ ast_clone(node->u.d_rop.aexp1),
+ ast_clone(node->u.d_rop.aexp2));
+ case NT_LET: return ast_let(
+ ast_clone(node->u.d_let.var),
+ ast_clone(node->u.d_let.aexp),
+ ast_clone(node->u.d_let.stm));
+ case NT_PROCDECL: return ast_procdecl(
+ node->u.d_procdecl.name,
+ ast_node_list_clone(node->u.d_procdecl.args),
+ ast_node_list_clone(node->u.d_procdecl.vargs),
+ ast_clone(node->u.d_procdecl.stm));
+ case NT_PROCCALL: return ast_proccall(
+ node->u.d_proccall.name,
+ ast_node_list_clone(node->u.d_proccall.args),
+ ast_node_list_clone(node->u.d_proccall.vargs));
+ default: assert(0);
+ }
} \ No newline at end of file
diff --git a/src/driver.c b/src/driver.c
index fc2a3ae..e3938a6 100644
--- a/src/driver.c
+++ b/src/driver.c
@@ -2,22 +2,23 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+
#include "interpreter.h"
#include "repl.h"
+
static void interpret_file(const char *path) {
- hashmap_t context = hashmap_create();
- exec_file(context, path);
- context_print(context);
- hashmap_free(context);
+ context_t context = context_create();
+ interp_file(context, path);
+ context_print_var_table(context);
+ context_free(context);
}
int main(int argc, char **argv) {
int opt;
- const char *script = NULL;
while ((opt = getopt(argc, argv, "i:h")) != -1) {
switch (opt){
- case 'i':
+ case 'i':
interpret_file(optarg);
return EXIT_SUCCESS;
case 'h':
diff --git a/src/hash_map.c b/src/hashmap.c
index 5f80205..a712134 100644
--- a/src/hash_map.c
+++ b/src/hashmap.c
@@ -1,15 +1,17 @@
-#include "hash_map.h"
-#include <stdio.h>
+#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;
- int value;
+ void *value;
struct Pair *next;
} Pair;
@@ -19,6 +21,13 @@ typedef struct HashMap {
size_t count;
} HashMap;
+typedef struct HashMapKeys {
+ char **keys;
+ size_t count;
+ size_t index;
+} HashMapKeys;
+
+
static unsigned int hash(const char *key, size_t size) {
unsigned int hash_value = 0;
while (*key) hash_value = (hash_value * 31) + *key++;
@@ -55,8 +64,8 @@ HashMap *hashmap_create(void) {
return map;
}
-void hashmap_insert(HashMap *map, const char *key, int value) {
- int *old_value = hashmap_get(map, key);
+void hashmap_insert(HashMap *map, const char *key, void *value) {
+ void **old_value = hashmap_get(map, key);
if (old_value) {
*old_value = value;
return;
@@ -73,7 +82,7 @@ void hashmap_insert(HashMap *map, const char *key, int value) {
map->count++;
}
-int *hashmap_get(HashMap *map, const char *key) {
+void **hashmap_get(HashMap *map, const char *key) {
unsigned int index = hash(key, map->size);
Pair *pair = map->table[index];
while (pair) {
@@ -83,7 +92,7 @@ int *hashmap_get(HashMap *map, const char *key) {
return NULL;
}
-void hashmap_delete(HashMap *map, const char *key) {
+int hashmap_delete(HashMap *map, const char *key) {
unsigned int index = hash(key, map->size);
Pair *pair = map->table[index];
Pair *prev = NULL;
@@ -94,11 +103,12 @@ void hashmap_delete(HashMap *map, const char *key) {
free(pair->key);
free(pair);
map->count--;
- return;
+ return 0;
}
prev = pair;
pair = pair->next;
}
+ return -1;
}
void hashmap_free(HashMap *map) {
@@ -115,7 +125,7 @@ void hashmap_free(HashMap *map) {
free(map);
}
-void hashmap_iterate(HashMap *map, void (*callback)(const char *key, int value)) {
+void hashmap_iterate(HashMap *map, void (*callback)(const char *key, void *value)) {
for (size_t i = 0; i < map->size; ++i) {
Pair *pair = map->table[i];
while (pair) {
@@ -123,4 +133,37 @@ void hashmap_iterate(HashMap *map, void (*callback)(const char *key, int value))
pair = pair->next;
}
}
+}
+
+HashMapKeys *hashmap_keys_create(HashMap *map) {
+ HashMapKeys *iter = malloc(sizeof(HashMapKeys));
+ assert(iter);
+ iter->keys = malloc(map->count * sizeof(char*));
+ assert(iter->keys);
+ iter->count = 0;
+ iter->index = 0;
+ for (size_t i = 0; i < map->size; ++i) {
+ Pair *pair = map->table[i];
+ while (pair) {
+ iter->keys[iter->count++] = strdup(pair->key);
+ pair = pair->next;
+ }
+ }
+ return iter;
+}
+
+const char *hashmap_keys_next(HashMapKeys *iter) {
+ if (iter->index < iter->count) {
+ return iter->keys[iter->index++];
+ }
+ return NULL;
+}
+
+void hashmap_keys_free(HashMapKeys *iter) {
+ if (!iter) return;
+ for (size_t i = 0; i < iter->count; ++i) {
+ free(iter->keys[i]);
+ }
+ free(iter->keys);
+ free(iter);
} \ No newline at end of file
diff --git a/src/interpreter.c b/src/interpreter.c
index 27626a8..af487c6 100644
--- a/src/interpreter.c
+++ b/src/interpreter.c
@@ -1,138 +1,204 @@
#include "interpreter.h"
+
#include <stdlib.h>
#include <stdio.h>
-#include <string.h>
+#include <assert.h>
+
+#include "hashmap.h"
+
typedef void *YY_BUFFER_STATE;
extern FILE *yyin;
extern ASTNode *ast_root;
extern int yyparse(void);
-extern void yyrestart (FILE *);
-extern YY_BUFFER_STATE yy_scan_string(const char *);
+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;
+
+
+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_set(hashmap_t context, const char *name, int val) {
- hashmap_insert(context, name, val);
+static void free_procdecl(const char *name, void *procdecl) {
+ ast_free((ASTNode*)procdecl);
}
-int context_get(hashmap_t context, const char *name) {
- int *val = hashmap_get(context, name);
+void context_free(Context *context) {
+ hashmap_free(context->var_table);
+ hashmap_iterate(context->proc_table, free_procdecl);
+ 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;
}
-static void print_var(const char *name, int val) {
- printf("%s = %d\n", name, val);
+void context_set_var(Context *context, const char *name, int val) {
+ hashmap_insert(context->var_table, name, (void*)val);
}
-void context_print(hashmap_t context) {
- hashmap_iterate(context, print_var);
+static void print_var(const char *name, void *val) {
+ printf("%s = %d\n", name, (int)val);
}
-static int eval_aexpr(hashmap_t context, ASTNode *node) {
+void context_print_var_table(Context *context) {
+ hashmap_iterate(context->var_table, print_var);
+}
+
+static ASTNode *context_get_proc(Context *context, const char *name) {
+ ASTNode **procdecl = (ASTNode**)hashmap_get(context->proc_table, name);
+ if (procdecl) return *procdecl;
+ return NULL;
+}
+
+static void context_set_proc(Context *context, const char *name, ASTNode *procdecl) {
+ hashmap_insert(context->proc_table, name, (void*)procdecl);
+}
+
+static int eval_aexpr(Context *context, ASTNode *node) {
switch (node->type) {
case NT_INT: return node->u.d_int.val;
- case NT_VAR: return context_get(context, node->u.d_var.name);
+ case NT_VAR: return context_get_var(context, node->u.d_var.name);
case NT_AOP: {
- int aexp1 = eval_aexpr(context, node->u.d_aop.aexp1);
- int aexp2 = eval_aexpr(context, node->u.d_aop.aexp2);
+ int aexp1_val = eval_aexpr(context, node->u.d_aop.aexp1);
+ int aexp2_val = eval_aexpr(context, node->u.d_aop.aexp2);
switch (node->u.d_aop.aop) {
- case AOP_ADD: return aexp1 + aexp2;
- case AOP_SUB: return aexp1 - aexp2;
- case AOP_MUL: return aexp1 * aexp2;
+ case AOP_ADD: return aexp1_val + aexp2_val;
+ case AOP_SUB: return aexp1_val - aexp2_val;
+ case AOP_MUL: return aexp1_val * aexp2_val;
+ default: assert(0);
}
}
- default:
- fprintf(stderr, "Bad aexpr node %d\n", node->type);
- exit(EXIT_FAILURE);
+ default: assert(0);
}
}
-static int eval_bexpr(hashmap_t context, ASTNode *node) {
+static int eval_bexpr(Context *context, ASTNode *node) {
switch (node->type) {
case NT_BOP: {
- int bexp1 = eval_bexpr(context, node->u.d_bop.bexp1);
- int bexp2 = eval_bexpr(context, node->u.d_bop.bexp2);
+ int bexp1_val = eval_bexpr(context, node->u.d_bop.bexp1);
+ int bexp2_val = eval_bexpr(context, node->u.d_bop.bexp2);
switch (node->u.d_bop.bop) {
- case BOP_AND: return bexp1 && bexp2;
- case BOP_OR: return bexp1 || bexp2;
+ case BOP_AND: return bexp1_val && bexp2_val;
+ case BOP_OR: return bexp1_val || bexp2_val;
+ default: assert(0);
}
}
- case NT_NOT:
- return !eval_bexpr(context, node->u.d_not.bexp);
+ case NT_NOT: return !eval_bexpr(context, node->u.d_not.bexp);
case NT_ROP: {
- int aexp1 = eval_aexpr(context, node->u.d_rop.aexp1);
- int aexp2 = eval_aexpr(context, node->u.d_rop.aexp2);
+ int aexp1_val = eval_aexpr(context, node->u.d_rop.aexp1);
+ int aexp2_val = eval_aexpr(context, node->u.d_rop.aexp2);
switch (node->u.d_rop.rop) {
- case ROP_EQ: return aexp1 == aexp2;
- case ROP_NE: return aexp1 != aexp2;
- case ROP_LT: return aexp1 < aexp2;
- case ROP_LE: return aexp1 <= aexp2;
- case ROP_GT: return aexp1 > aexp2;
- case ROP_GE: return aexp1 >= aexp2;
+ case ROP_EQ: return aexp1_val == aexp2_val;
+ case ROP_NE: return aexp1_val != aexp2_val;
+ case ROP_LT: return aexp1_val < aexp2_val;
+ case ROP_LE: return aexp1_val <= aexp2_val;
+ case ROP_GT: return aexp1_val > aexp2_val;
+ case ROP_GE: return aexp1_val >= aexp2_val;
+ default: assert(0);
}
}
- default:
- fprintf(stderr, "Bad bexpr node %d\n", node->type);
- exit(EXIT_FAILURE);
+ default: assert(0);
}
}
-void exec_stmt(hashmap_t context, ASTNode *node) {
- while (node) {
- switch (node->type) {
- case NT_SKIP:
- return;
- case NT_ASSIGN: {
- char *name = node->u.d_assign.var->u.d_var.name;
- int val = eval_aexpr(context, node->u.d_assign.aexp);
- context_set(context, name, val);
- return;
+void interp_ast(Context *context, ASTNode *node) {
+ switch (node->type) {
+ case NT_SKIP: return;
+ case NT_ASSIGN: {
+ char *name = node->u.d_assign.var->u.d_var.name;
+ int val = eval_aexpr(context, node->u.d_assign.aexp);
+ context_set_var(context, name, val);
+ return;
+ }
+ case NT_SEQ:
+ interp_ast(context, node->u.d_seq.stm1);
+ interp_ast(context, node->u.d_seq.stm2);
+ return;
+ case NT_IF:
+ if (eval_bexpr(context, node->u.d_if.bexp)) interp_ast(context, node->u.d_if.stm1);
+ else interp_ast(context, node->u.d_if.stm2);
+ return;
+ case NT_WHILE:
+ while (eval_bexpr(context, node->u.d_while.bexp)) interp_ast(context, node->u.d_while.stm);
+ return;
+ case NT_LET: {
+ char *name = node->u.d_let.var->u.d_var.name;
+ int old_val = context_get_var(context, name);
+ int new_val = eval_aexpr(context, node->u.d_let.aexp);
+ context_set_var(context, name, new_val);
+ interp_ast(context, node->u.d_let.stm);
+ context_set_var(context, name, old_val);
+ return;
+ }
+ case NT_PROCDECL: {
+ char *name = node->u.d_procdecl.name;
+ ASTNode *procdecl = ast_clone(node);
+ ASTNode *procdecl_old = context_get_proc(context, name);
+ if (procdecl_old) ast_free(procdecl_old);
+ context_set_proc(context, name, procdecl);
+ return;
+ }
+ case NT_PROCCALL: {
+ char *name = node->u.d_proccall.name;
+ ASTNode *procdecl = context_get_proc(context, name);
+ if (!procdecl) return;
+ ASTNodeList *caller_args = node->u.d_proccall.args;
+ ASTNodeList *callee_args = procdecl->u.d_procdecl.args;
+ Context *proc_context = context_create();
+ hashmap_keys_t keys = hashmap_keys_create(context->proc_table);
+ const char *key;
+ while ((key = hashmap_keys_next(keys)) != NULL) {
+ ASTNode *proc = context_get_proc(context, key);
+ assert(proc);
+ context_set_proc(proc_context, key, ast_clone(proc));
+ }
+ hashmap_keys_free(keys);
+ while (caller_args && callee_args) {
+ char *caller_arg_name = caller_args->node->u.d_var.name;
+ char *callee_arg_name = callee_args->node->u.d_var.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;
}
- case NT_SEQ:
- exec_stmt(context, node->u.d_seq.stm1);
- exec_stmt(context, node->u.d_seq.stm2);
- return;
- case NT_IF:
- if (eval_bexpr(context, node->u.d_if.bexp))
- exec_stmt(context, node->u.d_if.stm1);
- else
- exec_stmt(context, node->u.d_if.stm2);
- return;
- case NT_WHILE:
- while (eval_bexpr(context, node->u.d_while.bexp)) {
- exec_stmt(context, node->u.d_while.stm);
- }
- return;
- case NT_LET: {
- char *name = node->u.d_let.var->u.d_var.name;
- int old_val = context_get(context, name);
- int new_val = eval_aexpr(context, node->u.d_let.aexp);
- context_set(context, name, new_val);
- exec_stmt(context, node->u.d_let.stm);
- context_set(context, name, old_val);
- return;
+ interp_ast(proc_context, procdecl->u.d_procdecl.stm);
+ ASTNodeList *caller_vargs = node->u.d_proccall.vargs;
+ ASTNodeList *callee_vargs = procdecl->u.d_procdecl.vargs;
+ while (caller_vargs && callee_vargs) {
+ char *caller_varg_name = caller_vargs->node->u.d_var.name;
+ char *callee_varg_name = callee_vargs->node->u.d_var.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;
}
- default:
- fprintf(stderr, "Bad stmt node %d\n", node->type);
- exit(EXIT_FAILURE);
+ context_free(proc_context);
+ return;
}
+ default: assert(0);
}
}
-int exec_file (hashmap_t context, const char *path) {
+int interp_file (Context *context, const char *path) {
yyin = fopen(path, "r");
- if (!yyin) {
- perror(path);
- return -1;
- }
+ if (!yyin) return -1;
yyrestart(yyin);
if (!yyparse()) {
- exec_stmt(context, ast_root);
+ interp_ast(context, ast_root);
ast_free(ast_root);
} else {
- fprintf(stderr, "Parse error in %s\n", path);
fclose(yyin);
return -1;
}
@@ -140,13 +206,12 @@ int exec_file (hashmap_t context, const char *path) {
return 0;
}
-int exec_str (hashmap_t context, const char *str) {
+int interp_str (Context *context, const char *str) {
YY_BUFFER_STATE buf = yy_scan_string(str);
if (!yyparse()) {
- exec_stmt(context, ast_root);
+ interp_ast(context, ast_root);
ast_free(ast_root);
} else {
- fprintf(stderr, "Parse error\n");
yy_delete_buffer(buf);
return -1;
}
diff --git a/src/lexer.l b/src/lexer.l
index b2cbaab..285cbf7 100644
--- a/src/lexer.l
+++ b/src/lexer.l
@@ -19,10 +19,13 @@ WHITESPACE [ \t\r\n]+
"do" { return T_DO; }
"var" { return T_VAR; }
"in" { return T_IN; }
+"procedure" { return T_PROC; }
+"begin" { return T_BEGIN; }
"(" { return T_LPAREN; }
")" { return T_RPAREN; }
";" { return T_SEM; }
+"," { return T_COM; }
":=" { return T_ASSIGN; }
"+" { return T_PLUS; }
diff --git a/src/parser.y b/src/parser.y
index f03e54f..164b3cc 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -15,9 +15,10 @@ void yyerror(const char *s) {
%union {
- int num;
- char *id;
- struct ASTNode *node;
+ int num;
+ char *id;
+ struct ASTNode *node;
+ struct ASTNodeList *node_list;
}
%start prog
@@ -32,13 +33,12 @@ void yyerror(const char *s) {
%left T_PLUS T_MINUS
%left T_STAR
%right T_UMINUS
-%token T_END T_IF T_THEN T_ELSE T_WHILE T_DO T_VAR T_IN
-%token T_SKIP
+%token T_SKIP T_END T_IF T_THEN T_ELSE T_WHILE T_DO T_VAR T_IN T_PROC T_BEGIN
%token T_ASSIGN
-%token T_LPAREN T_RPAREN
-%token T_SEM
+%token T_LPAREN T_RPAREN T_COM T_SEM
-%type <node> prog stm var aexp bexp
+%type <node> prog stm var aexp bexp procd procc
+%type <node_list> args
%%
@@ -64,6 +64,10 @@ stm : T_SKIP
{ $$ = ast_while($2, $4); }
| T_VAR var T_ASSIGN aexp T_IN stm T_END
{ $$ = ast_let($2, $4, $6); }
+ | procd
+ { $$ = $1; }
+ | procc
+ { $$ = $1; }
;
var : T_ID
@@ -112,4 +116,17 @@ bexp : bexp T_OR bexp
{ $$ = ast_rop(ROP_EQ, ast_int(0), ast_int(1)); }
;
+args : var
+ { $$ = ast_node_list($1, NULL); }
+ | args T_COM var
+ { $$ = ast_node_list($3, $1); }
+ ;
+
+procd : T_PROC T_ID T_LPAREN args T_SEM args T_RPAREN T_BEGIN stm T_END
+ { $$ = ast_procdecl($2, $4, $6, $9); }
+ ;
+
+procc : T_ID T_LPAREN args T_SEM args T_RPAREN
+ { $$ = ast_proccall($1, $3, $5); }
+ ;
%%
diff --git a/src/repl.c b/src/repl.c
index 5ea9792..f6387a2 100644
--- a/src/repl.c
+++ b/src/repl.c
@@ -1,11 +1,15 @@
#include "repl.h"
-#include "interpreter.h"
-#include <readline/readline.h>
-#include <readline/history.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#include "interpreter.h"
+
+
static void print_help(void) {
printf(
"IMP REPL (type IMP statements or commands starting with '%%')\n"
@@ -17,7 +21,7 @@ static void print_help(void) {
" %%help show this message\n");
}
-static void repl_exec_command(hashmap_t context, const char *command) {
+static void repl_exec_command(context_t context, char *command) {
char *cmd = strtok(command, " \t");
if (strcmp(cmd, "%quit") == 0) {
exit(EXIT_SUCCESS);
@@ -26,30 +30,30 @@ static void repl_exec_command(hashmap_t context, const char *command) {
} else if (strcmp(cmd, "%run") == 0) {
char *file = strtok(NULL, " \t");
if (file) {
- if (!exec_file(context, file)) context_print(context);
+ if (!interp_file(context, file)) context_print_var_table(context);
} else {
fprintf(stderr, "Usage: %%run <path/to/file.imp>\n");
}
} else if (strcmp(cmd, "%set") == 0) {
char *var = strtok(NULL, " \t");
char *val = strtok(NULL, " \t");
- if (var && val) context_set(context, var, atoi(val));
+ if (var && val) context_set_var(context, var, atoi(val));
else fprintf(stderr, "Usage: %%set <var> <val>\n");
} else if (strcmp(cmd, "%print") == 0) {
char *var = strtok(NULL, " \t");
- if (var) printf("%s = %d\n", var, context_get(context, var));
- else context_print(context);
+ if (var) printf("%s = %d\n", var, context_get_var(context, var));
+ else context_print_var_table(context);
} else {
fprintf(stderr, "Unknown command: %s\n", cmd);
}
}
-static void repl_exec_statement(hashmap_t context, const char *statement) {
- if (!exec_str(context, statement)) context_print(context);
+static void repl_exec_statement(context_t context, const char *statement) {
+ if (!interp_str(context, statement)) context_print_var_table(context);
}
void repl(void) {
- hashmap_t context = hashmap_create();
+ context_t context = context_create();
char *line;
print_help();
@@ -61,5 +65,5 @@ void repl(void) {
}
printf("\n");
- hashmap_free(context);
+ context_free(context);
} \ No newline at end of file