aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlavian Kaufmann <flavian@flaviankaufmann.ch>2025-05-23 11:25:29 +0200
committerFlavian Kaufmann <flavian@flaviankaufmann.ch>2025-05-23 11:25:29 +0200
commitde59dbd1773dff06051b7b604977bcb2803ada4f (patch)
tree60be4de19aa7be4d4d99136c2bfbb824edfa2d90
parent987a7c553701251d48b11a2243892ecd74ce6c4d (diff)
downloadimp-de59dbd1773dff06051b7b604977bcb2803ada4f.tar.gz
imp-de59dbd1773dff06051b7b604977bcb2803ada4f.zip
[cleanup] ast
-rw-r--r--include/ast.h269
-rw-r--r--include/hashmap.h3
-rw-r--r--include/interpreter.h2
-rw-r--r--src/ast.c337
-rw-r--r--src/hashmap.c10
-rw-r--r--src/interpreter.c288
-rw-r--r--src/parser.y68
7 files changed, 519 insertions, 458 deletions
diff --git a/include/ast.h b/include/ast.h
index 12dce55..068372e 100644
--- a/include/ast.h
+++ b/include/ast.h
@@ -1,110 +1,165 @@
-#ifndef AST_H
-#define AST_H
+#ifndef IMP_AST_H
+#define IMP_AST_H
+/**
+ * @file ast.h
+ * @brief Defines the Abstract Syntax Tree (AST) structures and operations for the IMP language.
+ *
+ * Provides data structures, enums, and functions for creating, managing, cloning, and freeing AST nodes.
+ *
+ * @author Flavian Kaufmann
+ * @date 2025-05-23
+ */
-/* AST Node Types */
+
+/** AST node types for IMP language. */
+typedef enum {
+ IMP_AST_NT_SKIP, /**< No-operation (skip) */
+ IMP_AST_NT_ASSIGN, /**< Assignment statement */
+ IMP_AST_NT_SEQ, /**< Sequential composition of statements */
+ IMP_AST_NT_IF, /**< Conditional (if-then-else) statement */
+ IMP_AST_NT_WHILE, /**< While loop statement */
+ IMP_AST_NT_INT, /**< Integer literal */
+ IMP_AST_NT_VAR, /**< Variable reference */
+ IMP_AST_NT_AOP, /**< Arithmetic operation */
+ IMP_AST_NT_BOP, /**< Boolean operation */
+ IMP_AST_NT_NOT, /**< Boolean negation */
+ IMP_AST_NT_ROP, /**< Relational operation */
+ IMP_AST_NT_LET, /**< Local variable declaration (let-in-end) */
+ IMP_AST_NT_PROCDECL, /**< Procedure declaration */
+ IMP_AST_NT_PROCCALL /**< Procedure call */
+} IMP_ASTNodeType;
+
+/** Arithmetic operators. */
+typedef enum {
+ IMP_AST_AOP_ADD, /**< Addition (+) */
+ IMP_AST_AOP_SUB, /**< Subtraction (-) */
+ IMP_AST_AOP_MUL /**< Multiplication (*) */
+} IMP_ASTArithmeticOperator;
+
+/** Boolean operators. */
+typedef enum {
+ IMP_AST_BOP_AND, /**< Logical AND */
+ IMP_AST_BOP_OR /**< Logical OR */
+} IMP_ASTBooleanOperator;
+
+/** Relational operators. */
typedef enum {
- NT_SKIP, /* nop */
- NT_ASSIGN, /* assignment */
- NT_SEQ, /* sequential composition */
- NT_IF, /* if-then-else block */
- NT_WHILE, /* while loop */
- NT_INT, /* integer constant */
- NT_VAR, /* integer variable */
- NT_AOP, /* arithmetic operation */
- NT_BOP, /* boolean operation */
- NT_NOT, /* boolean not */
- NT_ROP, /* relational operation */
- NT_LET, /* let-in-end block (i.e. local variable) */
- NT_PROCDECL, /* procedure declaration */
- NT_PROCCALL /* procedure call */
-} NodeType;
-
-/* Arithmetic Operations */
-typedef enum {
- AOP_ADD, /* addition */
- AOP_SUB, /* subtraction */
- AOP_MUL /* multiplication */
-} AOp;
-
-/* Boolean Operations */
-typedef enum {
- BOP_AND, /* conjunction */
- BOP_OR /* disjunction */
-} BOp;
-
-/* Relational Operations */
-typedef enum {
- ROP_EQ, /* equals */
- ROP_NE, /* not equals */
- ROP_LT, /* less than */
- ROP_LE, /* less or equals */
- ROP_GT, /* greater than */
- ROP_GE /* greater or equals */
-} ROp;
-
-/* AST Node */
-typedef struct ASTNode {
- NodeType type;
- union { /* specific data for each node type */
- struct { struct ASTNode *var, *aexp; } d_assign;
- struct { struct ASTNode *stm1, *stm2; } d_seq;
- struct { struct ASTNode *bexp, *stm1, *stm2; } d_if;
- struct { struct ASTNode *bexp, *stm; } d_while;
- struct { int val; } d_int ;
- struct { char *name; } d_var;
- struct { AOp aop; struct ASTNode *aexp1, *aexp2; } d_aop;
- struct { BOp bop; struct ASTNode *bexp1, *bexp2; } d_bop;
- struct { struct ASTNode *bexp; } d_not;
- struct { ROp rop; struct ASTNode *aexp1, *aexp2; } d_rop;
- struct { struct ASTNode *var, *aexp, *stm; } d_let;
- struct { char *name; struct ASTNodeList *args, *vargs; struct ASTNode *stm; } d_procdecl;
- struct { char *name; struct ASTNodeList *args, *vargs; } d_proccall;
- } u;
-} ASTNode;
-
-/* AST Node List (i.e. linked list of AST Nodes) */
-typedef struct ASTNodeList {
- ASTNode *node;
- struct ASTNodeList *next;
-} ASTNodeList;
-
-
-/*
- Creates new node of specific type.
- The caller is responsible for freeing the top-most node, by calling ast_free.
- Any strings passed to the node are copied (i.e. strdup) and will also automatically be freed.
-*/
-ASTNode *ast_skip(void);
-ASTNode *ast_assign(ASTNode *var, ASTNode *aexp);
-ASTNode *ast_seq(ASTNode *stm1, ASTNode *stm2);
-ASTNode *ast_if(ASTNode *bexp, ASTNode *stm1, ASTNode *stm2);
-ASTNode *ast_while(ASTNode *bexp, ASTNode *stm);
-ASTNode *ast_int(int val);
-ASTNode *ast_var(char *name);
-ASTNode *ast_aop(AOp aop, ASTNode *aexp1, ASTNode *aexp2);
-ASTNode *ast_bop(BOp bop, ASTNode *bexp1, ASTNode *bexp2);
-ASTNode *ast_not(ASTNode *bexp);
-ASTNode *ast_rop(ROp rop, ASTNode *aexp1, ASTNode *aexp2);
-ASTNode *ast_let(ASTNode *var, ASTNode *aexp, ASTNode *stm);
-ASTNode *ast_procdecl(const char *name, ASTNodeList *args, ASTNodeList *vargs, ASTNode *stm);
-ASTNode *ast_proccall(const char *name, ASTNodeList *args, ASTNodeList *vargs);
-
-/*
- Creates node list,
- Must be used in conjunction with a node that takes a list (i.e. ast_procdecl).
- Will automatically be freed when the parent node is freed.
- */
-ASTNodeList *ast_node_list(ASTNode *node, ASTNodeList *list);
-
-/*
- Creates a deep copy of a node and it's sub nodes (recursively).
- caller is responsible for freeing top-most node.
-*/
-ASTNode *ast_clone(ASTNode *node);
-
-/* Recursively frees node and all sub nodes */
-void ast_free(ASTNode *node);
-
-
-#endif \ No newline at end of file
+ IMP_AST_ROP_EQ, /**< Equal (==) */
+ IMP_AST_ROP_NE, /**< Not equal (!=) */
+ IMP_AST_ROP_LT, /**< Less than (<) */
+ IMP_AST_ROP_LE, /**< Less or equal (<=) */
+ IMP_AST_ROP_GT, /**< Greater than (>) */
+ IMP_AST_ROP_GE /**< Greater or equal (>=) */
+} IMP_ASTRelationalOperator;
+
+/** Forward declaration for linked-list structure. */
+struct IMP_ASTNodeList;
+
+/** Abstract Syntax Tree node structure. */
+typedef struct IMP_ASTNode {
+ IMP_ASTNodeType type; /**< Type of the AST node. */
+
+ union {
+ struct { struct IMP_ASTNode *var, *aexpr; } assign;
+ struct { struct IMP_ASTNode *fst_stmt, *snd_stmt; } seq;
+ struct { struct IMP_ASTNode *cond_bexpr, *then_stmt, *else_stmt; } if_stmt;
+ struct { struct IMP_ASTNode *cond_bexpr, *body_stmt; } while_stmt;
+ struct { int val; } integer;
+ struct { char *name; } variable;
+ struct { IMP_ASTArithmeticOperator aopr; struct IMP_ASTNode *l_aexpr, *r_aexpr; } arith_op;
+ struct { IMP_ASTBooleanOperator bopr; struct IMP_ASTNode *l_bexpr, *r_bexpr; } bool_op;
+ struct { struct IMP_ASTNode *bexpr; } bool_not;
+ struct { IMP_ASTRelationalOperator ropr; struct IMP_ASTNode *l_aexpr, *r_aexpr; } rel_op;
+ struct { struct IMP_ASTNode *var, *aexpr, *body_stmt; } let_stmt;
+ struct { char *name; struct IMP_ASTNodeList *val_args, *var_args; struct IMP_ASTNode *body_stmt; } proc_decl;
+ struct { char *name; struct IMP_ASTNodeList *val_args, *var_args; } proc_call;
+ } data;
+} IMP_ASTNode;
+
+/** Linked list of AST nodes, primarily for arguments in procedures. */
+typedef struct IMP_ASTNodeList {
+ IMP_ASTNode *node; /**< AST node reference. */
+ struct IMP_ASTNodeList *next; /**< Pointer to the next node in the list. */
+} IMP_ASTNodeList;
+
+/* === AST Node Creation Functions === */
+
+/** Creates a 'skip' node (no-operation). */
+IMP_ASTNode *imp_ast_skip(void);
+
+/** Creates an assignment node. */
+IMP_ASTNode *imp_ast_assign(IMP_ASTNode *var, IMP_ASTNode *aexpr);
+
+/** Creates a sequence node (statement sequencing). */
+IMP_ASTNode *imp_ast_seq(IMP_ASTNode *fst_stmt, IMP_ASTNode *snd_stmt);
+
+/** Creates an if-then-else node. */
+IMP_ASTNode *imp_ast_if(IMP_ASTNode *cond_bexpr, IMP_ASTNode *then_stmt, IMP_ASTNode *else_stmt);
+
+/** Creates a while loop node. */
+IMP_ASTNode *imp_ast_while(IMP_ASTNode *cond_bexpr, IMP_ASTNode *body_stmt);
+
+/** Creates an integer literal node. */
+IMP_ASTNode *imp_ast_int(int val);
+
+/** Creates a variable reference node. (Name is copied internally.) */
+IMP_ASTNode *imp_ast_var(const char *name);
+
+/** Creates an arithmetic operation node. */
+IMP_ASTNode *imp_ast_aop(IMP_ASTArithmeticOperator aopr, IMP_ASTNode *l_aexpr, IMP_ASTNode *r_aexpr);
+
+/** Creates a boolean operation node. */
+IMP_ASTNode *imp_ast_bop(IMP_ASTBooleanOperator bopr, IMP_ASTNode *l_bexpr, IMP_ASTNode *r_bexpr);
+
+/** Creates a boolean negation node. */
+IMP_ASTNode *imp_ast_not(IMP_ASTNode *bexpr);
+
+/** Creates a relational operation node. */
+IMP_ASTNode *imp_ast_rop(IMP_ASTRelationalOperator ropr, IMP_ASTNode *l_aexpr, IMP_ASTNode *r_aexpr);
+
+/** Creates a let-in-end (local variable declaration) node. */
+IMP_ASTNode *imp_ast_let(IMP_ASTNode *var, IMP_ASTNode *aexpr, IMP_ASTNode *body_stmt);
+
+/** Creates a procedure declaration node. (Name is copied internally.) */
+IMP_ASTNode *imp_ast_procdecl(const char *name, IMP_ASTNodeList *val_args, IMP_ASTNodeList *var_args, IMP_ASTNode *body_stmt);
+
+/** Creates a procedure call node. (Name is copied internally.) */
+IMP_ASTNode *imp_ast_proccall(const char *name, IMP_ASTNodeList *val_args, IMP_ASTNodeList *var_args);
+
+/* === AST Utility Functions === */
+
+/**
+ * Creates a deep copy of the given AST node and all its sub-nodes.
+ *
+ * @param node Node to clone.
+ * @return Pointer to cloned node; must be freed by the caller.
+ */
+IMP_ASTNode *imp_ast_clone(const IMP_ASTNode *node);
+
+/**
+ * Frees an AST node and recursively all its sub-nodes.
+ *
+ * @param node Node to free.
+ */
+void imp_ast_free(IMP_ASTNode *node);
+
+/**
+ * Creates a new linked list of AST nodes.
+ *
+ * @param node Node to prepend to the list.
+ * @param list Existing list or NULL if starting a new one.
+ * @return New head of the list.
+ *
+ * @note Ownership of the list nodes is transferred; freed automatically when parent AST node is freed.
+ */
+IMP_ASTNodeList *imp_ast_list(IMP_ASTNode *node, IMP_ASTNodeList *list);
+
+/**
+ * Frees a linked list of AST nodes. Typically not required directly, as it's freed with the parent AST node.
+ *
+ * @param list List to free.
+ */
+void imp_ast_list_free(IMP_ASTNodeList *list);
+
+#endif /* IMP_AST_H */ \ No newline at end of file
diff --git a/include/hashmap.h b/include/hashmap.h
index 57ebafe..7cc20b1 100644
--- a/include/hashmap.h
+++ b/include/hashmap.h
@@ -7,6 +7,7 @@ typedef struct HashMap *hashmap_t;
/* Hashmap Key Iterator Handle */
typedef struct HashMapKeysIter *hashmap_keys_iter_t;
+
/*
Creates hashmap that maps char* to void*.
Keys are copied, and will be freed when the hashmap is freed.
@@ -31,7 +32,7 @@ void **hashmap_get(hashmap_t map, const char *key);
Inserts element with given key.
If key already exists, the old element is replaced (caller is responsible for freeing beforehand).
*/
-void hashmap_insert(hashmap_t map, const char *key, void *value);
+void hashmap_insert(hashmap_t map, const char *key, void *element);
/*
Deletes element with given key.
diff --git a/include/interpreter.h b/include/interpreter.h
index 09f1e18..5eff23f 100644
--- a/include/interpreter.h
+++ b/include/interpreter.h
@@ -16,7 +16,7 @@ void context_set_var(context_t context, const char *name, int value);
void context_print_var_table(context_t context);
void context_print_proc_table(context_t context);
-int interp_ast(context_t context, ASTNode *node);
+int interp_ast(context_t context, IMP_ASTNode *node);
int interp_file (context_t context, const char *path);
int interp_str (context_t context, const char *str);
diff --git a/src/ast.c b/src/ast.c
index ba8dc9f..03e6100 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -5,240 +5,245 @@
#include <assert.h>
-static ASTNode *new_node(NodeType type) {
- ASTNode *node = malloc(sizeof(ASTNode));
- assert(node);
+static IMP_ASTNode *ast_create(IMP_ASTNodeType type) {
+ IMP_ASTNode *node = malloc(sizeof(IMP_ASTNode));
+ assert(node && "Memory allocation failed");
node->type = type;
return node;
}
-ASTNode *ast_skip(void) {
- return new_node(NT_SKIP);
+static IMP_ASTNodeList *ast_list_clone(IMP_ASTNodeList *list) {
+ if (!list) return NULL;
+ return imp_ast_list(imp_ast_clone(list->node), ast_list_clone(list->next));
}
-ASTNode *ast_assign(ASTNode *var, ASTNode *aexp) {
- ASTNode *node = new_node(NT_ASSIGN);
- node->u.d_assign.var = var;
- node->u.d_assign.aexp = aexp;
- return node;
+IMP_ASTNode *imp_ast_skip(void) {
+ return ast_create(IMP_AST_NT_SKIP);
}
-ASTNode *ast_seq(ASTNode *stm1, ASTNode *stm2) {
- ASTNode *node = new_node(NT_SEQ);
- node->u.d_seq.stm1 = stm1;
- node->u.d_seq.stm2 = stm2;
+IMP_ASTNode *imp_ast_assign(IMP_ASTNode *var, IMP_ASTNode *aexpr) {
+ IMP_ASTNode *node = ast_create(IMP_AST_NT_ASSIGN);
+ node->data.assign.var = var;
+ node->data.assign.aexpr = aexpr;
return node;
}
-ASTNode *ast_if(ASTNode *bexp, ASTNode *stm1, ASTNode *stm2) {
- ASTNode *node = new_node(NT_IF);
- node->u.d_if.bexp = bexp;
- node->u.d_if.stm1 = stm1;
- node->u.d_if.stm2 = stm2;
+IMP_ASTNode *imp_ast_seq(IMP_ASTNode *fst_stmt, IMP_ASTNode *snd_stmt) {
+ IMP_ASTNode *node = ast_create(IMP_AST_NT_SEQ);
+ node->data.seq.fst_stmt = fst_stmt;
+ node->data.seq.snd_stmt = snd_stmt;
return node;
}
-ASTNode *ast_while(ASTNode *bexp, ASTNode *stm) {
- ASTNode *node = new_node(NT_WHILE);
- node->u.d_while.bexp = bexp;
- node->u.d_while.stm = stm;
+IMP_ASTNode *imp_ast_if(IMP_ASTNode *cond_bexpr, IMP_ASTNode *then_stmt, IMP_ASTNode *else_stmt) {
+ IMP_ASTNode *node = ast_create(IMP_AST_NT_IF);
+ node->data.if_stmt.cond_bexpr = cond_bexpr;
+ node->data.if_stmt.then_stmt = then_stmt;
+ node->data.if_stmt.else_stmt = else_stmt;
return node;
}
-ASTNode *ast_int(int val) {
- ASTNode *node = new_node(NT_INT);
- node->u.d_int.val = val;
+IMP_ASTNode *imp_ast_while(IMP_ASTNode *cond_bexpr, IMP_ASTNode *body_stmt) {
+ IMP_ASTNode *node = ast_create(IMP_AST_NT_WHILE);
+ node->data.while_stmt.cond_bexpr = cond_bexpr;
+ node->data.while_stmt.body_stmt = body_stmt;
return node;
}
-ASTNode *ast_var(char *name) {
- ASTNode *node = new_node(NT_VAR);
- node->u.d_var.name = strdup(name);
- assert(node->u.d_var.name);
+IMP_ASTNode *imp_ast_int(int val) {
+ IMP_ASTNode *node = ast_create(IMP_AST_NT_INT);
+ node->data.integer.val = val;
return node;
}
-ASTNode *ast_aop(AOp aop, ASTNode *aexp1, ASTNode *aexp2) {
- ASTNode *node = new_node(NT_AOP);
- node->u.d_aop.aexp1 = aexp1;
- node->u.d_aop.aexp2 = aexp2;
- node->u.d_aop.aop = aop;
+IMP_ASTNode *imp_ast_var(const char *name) {
+ IMP_ASTNode *node = ast_create(IMP_AST_NT_VAR);
+ node->data.variable.name = strdup(name);
+ assert(node->data.variable.name && "Memory allocation failed");
return node;
}
-ASTNode *ast_bop(BOp bop, ASTNode *bexp1, ASTNode *bexp2) {
- ASTNode *node = new_node(NT_BOP);
- node->u.d_bop.bexp1 = bexp1;
- node->u.d_bop.bexp2 = bexp2;
- node->u.d_bop.bop = bop;
+IMP_ASTNode *imp_ast_aop(IMP_ASTArithmeticOperator aopr, IMP_ASTNode *l_aexpr, IMP_ASTNode *r_aexpr) {
+ IMP_ASTNode *node = ast_create(IMP_AST_NT_AOP);
+ node->data.arith_op.aopr = aopr;
+ node->data.arith_op.l_aexpr = l_aexpr;
+ node->data.arith_op.r_aexpr = r_aexpr;
return node;
}
-ASTNode *ast_not(ASTNode *bexp) {
- ASTNode *node = new_node(NT_NOT);
- node->u.d_not.bexp = bexp;
+IMP_ASTNode *imp_ast_bop(IMP_ASTBooleanOperator bopr, IMP_ASTNode *l_bexpr, IMP_ASTNode *r_bexpr) {
+ IMP_ASTNode *node = ast_create(IMP_AST_NT_BOP);
+ node->data.bool_op.bopr = bopr;
+ node->data.bool_op.l_bexpr = l_bexpr;
+ node->data.bool_op.r_bexpr = r_bexpr;
return node;
}
-ASTNode *ast_rop(ROp rop, ASTNode *aexp1, ASTNode *aexp2) {
- ASTNode *node = new_node(NT_ROP);
- node->u.d_rop.aexp1 = aexp1;
- node->u.d_rop.aexp2 = aexp2;
- node->u.d_rop.rop = rop;
+IMP_ASTNode *imp_ast_not(IMP_ASTNode *bexpr) {
+ IMP_ASTNode *node = ast_create(IMP_AST_NT_NOT);
+ node->data.bool_not.bexpr = bexpr;
return node;
}
-ASTNode *ast_let(ASTNode *var, ASTNode *aexp, ASTNode *stm) {
- ASTNode *node = new_node(NT_LET);
- node->u.d_let.var = var;
- node->u.d_let.aexp = aexp;
- node->u.d_let.stm = stm;
+IMP_ASTNode *imp_ast_rop(IMP_ASTRelationalOperator ropr, IMP_ASTNode *l_aexpr, IMP_ASTNode *r_aexpr) {
+ IMP_ASTNode *node = ast_create(IMP_AST_NT_ROP);
+ node->data.rel_op.ropr = ropr;
+ node->data.rel_op.l_aexpr = l_aexpr;
+ node->data.rel_op.r_aexpr = r_aexpr;
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;
+IMP_ASTNode *imp_ast_let(IMP_ASTNode *var, IMP_ASTNode *aexpr, IMP_ASTNode *body_stmt) {
+ IMP_ASTNode *node = ast_create(IMP_AST_NT_LET);
+ node->data.let_stmt.var = var;
+ node->data.let_stmt.aexpr = aexpr;
+ node->data.let_stmt.body_stmt = body_stmt;
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;
+IMP_ASTNode *imp_ast_procdecl(const char *name, IMP_ASTNodeList *val_args, IMP_ASTNodeList *var_args, IMP_ASTNode *body_stmt) {
+ IMP_ASTNode *node = ast_create(IMP_AST_NT_PROCDECL);
+ node->data.proc_decl.name = strdup(name);
+ assert(node->data.proc_decl.name && "Memory allocation failed");
+ node->data.proc_decl.val_args = val_args;
+ node->data.proc_decl.var_args = var_args;
+ node->data.proc_decl.body_stmt = body_stmt;
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;
+IMP_ASTNode *imp_ast_proccall(const char *name, IMP_ASTNodeList *val_args, IMP_ASTNodeList *var_args) {
+ IMP_ASTNode *node = ast_create(IMP_AST_NT_PROCCALL);
+ node->data.proc_call.name = strdup(name);
+ assert(node->data.proc_call.name && "Memory allocation failed");
+ node->data.proc_call.val_args = val_args;
+ node->data.proc_call.var_args = var_args;
+ return node;
}
-static void ast_free_node_list(ASTNodeList *list) {
- if (!list) return;
- ast_free(list->node);
- ast_free_node_list(list->next);
- free(list);
+IMP_ASTNode *imp_ast_clone(const IMP_ASTNode *node) {
+ if (!node) return NULL;
+ switch (node->type) {
+ case IMP_AST_NT_SKIP: return imp_ast_skip();
+ case IMP_AST_NT_ASSIGN: return imp_ast_assign(
+ imp_ast_clone(node->data.assign.var),
+ imp_ast_clone(node->data.assign.aexpr));
+ case IMP_AST_NT_SEQ: return imp_ast_seq(
+ imp_ast_clone(node->data.seq.fst_stmt),
+ imp_ast_clone(node->data.seq.snd_stmt));
+ case IMP_AST_NT_IF: return imp_ast_if(
+ imp_ast_clone(node->data.if_stmt.cond_bexpr),
+ imp_ast_clone(node->data.if_stmt.then_stmt),
+ imp_ast_clone(node->data.if_stmt.else_stmt));
+ case IMP_AST_NT_WHILE: return imp_ast_while(
+ imp_ast_clone(node->data.while_stmt.cond_bexpr),
+ imp_ast_clone(node->data.while_stmt.body_stmt));
+ case IMP_AST_NT_INT: return imp_ast_int(node->data.integer.val);
+ case IMP_AST_NT_VAR: return imp_ast_var(node->data.variable.name);
+ case IMP_AST_NT_AOP: return imp_ast_aop(
+ node->data.arith_op.aopr,
+ imp_ast_clone(node->data.arith_op.l_aexpr),
+ imp_ast_clone(node->data.arith_op.r_aexpr));
+ case IMP_AST_NT_BOP: return imp_ast_bop(
+ node->data.bool_op.bopr,
+ imp_ast_clone(node->data.bool_op.l_bexpr),
+ imp_ast_clone(node->data.bool_op.r_bexpr));
+ case IMP_AST_NT_NOT: return imp_ast_not(
+ imp_ast_clone(node->data.bool_not.bexpr));
+ case IMP_AST_NT_ROP: return imp_ast_rop(
+ node->data.rel_op.ropr,
+ imp_ast_clone(node->data.rel_op.l_aexpr),
+ imp_ast_clone(node->data.rel_op.r_aexpr));
+ case IMP_AST_NT_LET: return imp_ast_let(
+ imp_ast_clone(node->data.let_stmt.var),
+ imp_ast_clone(node->data.let_stmt.aexpr),
+ imp_ast_clone(node->data.let_stmt.body_stmt));
+ case IMP_AST_NT_PROCDECL: return imp_ast_procdecl(
+ node->data.proc_decl.name,
+ ast_list_clone(node->data.proc_decl.val_args),
+ ast_list_clone(node->data.proc_decl.var_args),
+ imp_ast_clone(node->data.proc_decl.body_stmt));
+ case IMP_AST_NT_PROCCALL: return imp_ast_proccall(
+ node->data.proc_call.name,
+ ast_list_clone(node->data.proc_call.val_args),
+ ast_list_clone(node->data.proc_call.var_args));
+ default: assert(0 && "Unknown AST node type");
+ }
}
-void ast_free(ASTNode *node) {
+void imp_ast_free(IMP_ASTNode *node) {
if (!node) return;
switch (node->type) {
- case NT_SKIP:
+ case IMP_AST_NT_SKIP:
break;
- case NT_ASSIGN:
- ast_free(node->u.d_assign.var);
- ast_free(node->u.d_assign.aexp);
+ case IMP_AST_NT_ASSIGN:
+ imp_ast_free(node->data.assign.var);
+ imp_ast_free(node->data.assign.aexpr);
break;
- case NT_SEQ:
- ast_free(node->u.d_seq.stm1);
- ast_free(node->u.d_seq.stm2);
+ case IMP_AST_NT_SEQ:
+ imp_ast_free(node->data.seq.fst_stmt);
+ imp_ast_free(node->data.seq.snd_stmt);
break;
- case NT_IF:
- ast_free(node->u.d_if.bexp);
- ast_free(node->u.d_if.stm1);
- ast_free(node->u.d_if.stm2);
+ 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);
break;
- case NT_WHILE:
- ast_free(node->u.d_while.bexp);
- ast_free(node->u.d_while.stm);
+ case IMP_AST_NT_WHILE:
+ imp_ast_free(node->data.while_stmt.cond_bexpr);
+ imp_ast_free(node->data.while_stmt.body_stmt);
break;
- case NT_INT:
+ case IMP_AST_NT_INT:
break;
- case NT_VAR:
- free(node->u.d_var.name);
+ case IMP_AST_NT_VAR:
+ free(node->data.variable.name);
break;
- case NT_AOP:
- ast_free(node->u.d_aop.aexp1);
- ast_free(node->u.d_aop.aexp2);
+ case IMP_AST_NT_AOP:
+ imp_ast_free(node->data.arith_op.l_aexpr);
+ imp_ast_free(node->data.arith_op.r_aexpr);
break;
- case NT_BOP:
- ast_free(node->u.d_bop.bexp1);
- ast_free(node->u.d_bop.bexp2);
+ case IMP_AST_NT_BOP:
+ imp_ast_free(node->data.bool_op.l_bexpr);
+ imp_ast_free(node->data.bool_op.r_bexpr);
break;
- case NT_ROP:
- ast_free(node->u.d_rop.aexp1);
- ast_free(node->u.d_rop.aexp2);
+ case IMP_AST_NT_ROP:
+ imp_ast_free(node->data.rel_op.l_aexpr);
+ imp_ast_free(node->data.rel_op.r_aexpr);
break;
- case NT_NOT:
- ast_free(node->u.d_not.bexp);
+ case IMP_AST_NT_NOT:
+ imp_ast_free(node->data.bool_not.bexpr);
break;
- case NT_LET:
- ast_free(node->u.d_let.var);
- ast_free(node->u.d_let.aexp);
- ast_free(node->u.d_let.stm);
+ 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);
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);
+ 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);
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);
+ 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);
break;
- default: assert(0);
+ default: assert(0 && "Unknown AST node type");
}
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));
+IMP_ASTNodeList *imp_ast_list(IMP_ASTNode *node, IMP_ASTNodeList *list) {
+ IMP_ASTNodeList *new_list = malloc(sizeof(IMP_ASTNodeList));
+ assert(new_list && "Memory allocation failed");
+ new_list->node = node;
+ new_list->next = list;
+ return new_list;
}
-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);
- }
+void imp_ast_list_free(IMP_ASTNodeList *list) {
+ if (!list) return;
+ imp_ast_free(list->node);
+ imp_ast_list_free(list->next);
+ free(list);
} \ No newline at end of file
diff --git a/src/hashmap.c b/src/hashmap.c
index bf214d8..89d0106 100644
--- a/src/hashmap.c
+++ b/src/hashmap.c
@@ -11,7 +11,7 @@
typedef struct Pair {
char *key;
- void *value;
+ void *element;
struct Pair *next;
} Pair;
@@ -64,10 +64,10 @@ HashMap *hashmap_create(void) {
return map;
}
-void hashmap_insert(HashMap *map, const char *key, void *value) {
+void hashmap_insert(HashMap *map, const char *key, void *element) {
void **old_value = hashmap_get(map, key);
if (old_value) {
- *old_value = value;
+ *old_value = element;
return;
}
if ((float)map->count / map->size > LOAD_FACTOR_THRESHOLD) resize(map);
@@ -76,7 +76,7 @@ void hashmap_insert(HashMap *map, const char *key, void *value) {
assert(new_pair);
new_pair->key = strdup(key);
assert(new_pair->key);
- new_pair->value = value;
+ new_pair->element = element;
new_pair->next = map->table[index];
map->table[index] = new_pair;
map->count++;
@@ -86,7 +86,7 @@ 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->value;
+ if (strcmp(pair->key, key) == 0) return &pair->element;
pair = pair->next;
}
return NULL;
diff --git a/src/interpreter.c b/src/interpreter.c
index ecf26bd..c0678b7 100644
--- a/src/interpreter.c
+++ b/src/interpreter.c
@@ -9,7 +9,7 @@
typedef void *YY_BUFFER_STATE;
extern FILE *yyin;
-extern ASTNode *ast_root;
+extern IMP_ASTNode *ast_root;
extern int yyparse(void);
extern void yyrestart (FILE*);
extern YY_BUFFER_STATE yy_scan_string(const char*);
@@ -21,13 +21,13 @@ typedef struct Context{
} Context;
-static ASTNode *context_get_proc(Context *context, const char *name) {
- ASTNode **procdecl = (ASTNode**)hashmap_get(context->proc_table, name);
+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, ASTNode *procdecl) {
+static void context_set_proc(Context *context, const char *name, IMP_ASTNode *procdecl) {
hashmap_insert(context->proc_table, name, (void*)procdecl);
}
@@ -44,9 +44,9 @@ void context_free(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) {
- ASTNode *procdecl = context_get_proc(context, key);
+ IMP_ASTNode *procdecl = context_get_proc(context, key);
assert(procdecl);
- ast_free(procdecl);
+ imp_ast_free(procdecl);
}
hashmap_keys_iter_free(iter);
hashmap_free(context->proc_table);
@@ -77,18 +77,18 @@ 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) {
- ASTNode *procdecl = context_get_proc(context, key);
+ IMP_ASTNode *procdecl = context_get_proc(context, key);
printf("%s(", key);
- ASTNodeList *args = procdecl->u.d_procdecl.args;
+ IMP_ASTNodeList *args = procdecl->data.proc_decl.val_args;
while (args) {
- printf("%s", args->node->u.d_var.name);
+ printf("%s", args->node->data.variable.name);
args = args->next;
if (args) printf(", ");
}
printf("; ");
- ASTNodeList *vargs = procdecl->u.d_procdecl.vargs;
+ IMP_ASTNodeList *vargs = procdecl->data.proc_decl.var_args;
while (vargs) {
- printf("%s", vargs->node->u.d_var.name);
+ printf("%s", vargs->node->data.variable.name);
vargs = vargs->next;
if (vargs) printf(", ");
}
@@ -97,134 +97,134 @@ void context_print_proc_table(Context *context) {
hashmap_keys_iter_free(iter);
}
-void ast_print(ASTNode *node, int depth) {
+void ast_print(IMP_ASTNode *node, int depth) {
int indent = depth * 2;
switch (node->type) {
- case NT_SKIP: {
+ case IMP_AST_NT_SKIP: {
printf("%*sSKIP\n", indent, "");
break;
}
- case NT_ASSIGN: {
+ case IMP_AST_NT_ASSIGN: {
printf("%*sASSIGN %s=", indent, "",
- node->u.d_assign.var->u.d_var.name);
- ast_print(node->u.d_assign.aexp, 0);
+ node->data.assign.var->data.variable.name);
+ ast_print(node->data.assign.aexpr, 0);
printf("\n");
break;
}
- case NT_SEQ: {
- ast_print(node->u.d_seq.stm1, depth);
+ case IMP_AST_NT_SEQ: {
+ ast_print(node->data.seq.fst_stmt, depth);
printf("%*sSEQ\n", indent, "");
- ast_print(node->u.d_seq.stm2, depth);
+ ast_print(node->data.seq.snd_stmt, depth);
break;
}
- case NT_IF: {
+ case IMP_AST_NT_IF: {
printf("%*sIF (", indent, "");
- ast_print(node->u.d_if.bexp, 0);
+ ast_print(node->data.if_stmt.cond_bexpr, 0);
printf(")\n");
- ast_print(node->u.d_if.stm1, depth + 1);
+ ast_print(node->data.if_stmt.then_stmt, depth + 1);
printf("%*sELSE\n", indent, "");
- ast_print(node->u.d_if.stm2, depth + 1);
+ ast_print(node->data.if_stmt.else_stmt, depth + 1);
break;
}
- case NT_WHILE: {
+ case IMP_AST_NT_WHILE: {
printf("%*sWHILE (", indent, "");
- ast_print(node->u.d_while.bexp, 0);
+ ast_print(node->data.while_stmt.cond_bexpr, 0);
printf(")\n");
- ast_print(node->u.d_while.stm, depth + 1);
+ ast_print(node->data.while_stmt.body_stmt, depth + 1);
break;
}
- case NT_INT: {
- printf("%d", node->u.d_int.val);
+ case IMP_AST_NT_INT: {
+ printf("%d", node->data.integer.val);
break;
}
- case NT_VAR: {
- printf("%s", node->u.d_var.name);
+ case IMP_AST_NT_VAR: {
+ printf("%s", node->data.variable.name);
break;
}
- case NT_AOP: {
+ case IMP_AST_NT_AOP: {
printf("(");
- ast_print(node->u.d_aop.aexp1, 0);
- switch (node->u.d_aop.aop) {
- case AOP_ADD: printf(" + "); break;
- case AOP_SUB: printf(" - "); break;
- case AOP_MUL: printf(" * "); break;
+ 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->u.d_aop.aexp2, 0);
+ ast_print(node->data.arith_op.r_aexpr, 0);
printf(")");
break;
}
- case NT_BOP: {
+ case IMP_AST_NT_BOP: {
printf("(");
- ast_print(node->u.d_bop.bexp1, 0);
- switch (node->u.d_bop.bop) {
- case BOP_AND: printf(" && "); break;
- case BOP_OR: printf(" || "); break;
+ 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->u.d_bop.bexp2, 0);
+ ast_print(node->data.bool_op.r_bexpr, 0);
printf(")");
break;
}
- case NT_NOT: {
+ case IMP_AST_NT_NOT: {
printf("!");
- ast_print(node->u.d_not.bexp, 0);
+ ast_print(node->data.bool_not.bexpr, 0);
break;
}
- case NT_ROP: {
+ case IMP_AST_NT_ROP: {
printf("(");
- ast_print(node->u.d_rop.aexp1, 0);
- switch (node->u.d_rop.rop) {
- case ROP_EQ: printf(" == "); break;
- case ROP_NE: printf(" != "); break;
- case ROP_LT: printf(" < "); break;
- case ROP_LE: printf(" <= "); break;
- case ROP_GT: printf(" > "); break;
- case ROP_GE: printf(" >= "); break;
+ 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->u.d_rop.aexp2, 0);
+ ast_print(node->data.rel_op.r_aexpr, 0);
printf(")");
break;
}
- case NT_LET: {
- printf("%*sLET %s = ", indent, "", node->u.d_let.var->u.d_var.name);
- ast_print(node->u.d_let.aexp, 0);
+ 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->u.d_let.stm, depth + 1);
+ ast_print(node->data.let_stmt.body_stmt, depth + 1);
break;
}
- case NT_PROCDECL: {
- printf("%*sPROC %s(", indent, "", node->u.d_procdecl.name);
- ASTNodeList *args = node->u.d_procdecl.args;
+ 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->u.d_var.name);
+ printf("%s", args->node->data.variable.name);
args = args->next;
if (args) printf(", ");
}
printf("; ");
- ASTNodeList *vargs = node->u.d_procdecl.vargs;
+ IMP_ASTNodeList *vargs = node->data.proc_decl.var_args;
while (vargs) {
- printf("%s", vargs->node->u.d_var.name);
+ printf("%s", vargs->node->data.variable.name);
vargs = vargs->next;
if (vargs) printf(", ");
}
printf(")\n");
- ast_print(node->u.d_procdecl.stm, depth + 1);
+ ast_print(node->data.proc_decl.body_stmt, depth + 1);
break;
}
- case NT_PROCCALL: {
- printf("%*sCALL %s(", indent, "", node->u.d_proccall.name);
- ASTNodeList *args = node->u.d_proccall.args;
+ 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->u.d_var.name);
+ printf("%s", args->node->data.variable.name);
args = args->next;
if (args) printf(", ");
}
printf("; ");
- ASTNodeList *vargs = node->u.d_proccall.vargs;
+ IMP_ASTNodeList *vargs = node->data.proc_call.var_args;
while (vargs) {
- printf("%s", vargs->node->u.d_var.name);
+ printf("%s", vargs->node->data.variable.name);
vargs = vargs->next;
if (vargs) printf(", ");
}
@@ -235,17 +235,17 @@ void ast_print(ASTNode *node, int depth) {
}
}
-static int eval_aexpr(Context *context, ASTNode *node) {
+static int eval_aexpr(Context *context, IMP_ASTNode *node) {
switch (node->type) {
- case NT_INT: return node->u.d_int.val;
- case NT_VAR: return context_get_var(context, node->u.d_var.name);
- case NT_AOP: {
- 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_val + aexp2_val;
- case AOP_SUB: return aexp1_val - aexp2_val;
- case AOP_MUL: return aexp1_val * aexp2_val;
+ 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_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);
+ 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;
default: assert(0);
}
}
@@ -253,28 +253,28 @@ static int eval_aexpr(Context *context, ASTNode *node) {
}
}
-static int eval_bexpr(Context *context, ASTNode *node) {
+static int eval_bexpr(Context *context, IMP_ASTNode *node) {
switch (node->type) {
- case NT_BOP: {
- 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_val && bexp2_val;
- case BOP_OR: return bexp1_val || bexp2_val;
+ 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);
+ 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;
default: assert(0);
}
}
- case NT_NOT: return !eval_bexpr(context, node->u.d_not.bexp);
- case NT_ROP: {
- 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_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;
+ 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);
+ 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;
default: assert(0);
}
}
@@ -282,26 +282,26 @@ static int eval_bexpr(Context *context, ASTNode *node) {
}
}
-static int interp_proccall(Context *context, ASTNode *node) {
- char *name = node->u.d_proccall.name;
- ASTNode *procdecl = context_get_proc(context, name);
+static int interp_proccall(Context *context, IMP_ASTNode *node) {
+ const char *name = node->data.proc_call.name;
+ IMP_ASTNode *procdecl = context_get_proc(context, name);
if (!procdecl) {
fprintf(stderr, "Error: procedure %s not defined\n", name);
return -1;
}
- ASTNodeList *caller_args = node->u.d_proccall.args;
- ASTNodeList *callee_args = procdecl->u.d_procdecl.args;
+ 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) {
- ASTNode *proc = context_get_proc(context, key);
- context_set_proc(proc_context, key, ast_clone(proc));
+ 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) {
- char *caller_arg_name = caller_args->node->u.d_var.name;
- char *callee_arg_name = callee_args->node->u.d_var.name;
+ 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;
@@ -311,15 +311,15 @@ static int interp_proccall(Context *context, ASTNode *node) {
context_free(proc_context);
return -1;
}
- if (interp_ast(proc_context, procdecl->u.d_procdecl.stm)) {
+ if (interp_ast(proc_context, procdecl->data.proc_decl.body_stmt)) {
context_free(proc_context);
return -1;
}
- ASTNodeList *caller_vargs = node->u.d_proccall.vargs;
- ASTNodeList *callee_vargs = procdecl->u.d_procdecl.vargs;
+ 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) {
- char *caller_varg_name = caller_vargs->node->u.d_var.name;
- char *callee_varg_name = callee_vargs->node->u.d_var.name;
+ 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;
@@ -333,48 +333,48 @@ static int interp_proccall(Context *context, ASTNode *node) {
return 0;
}
-int interp_ast(Context *context, ASTNode *node) {
+int interp_ast(Context *context, IMP_ASTNode *node) {
switch (node->type) {
- case NT_SKIP: return 0;
- case NT_ASSIGN: {
- char *name = node->u.d_assign.var->u.d_var.name;
- int val = eval_aexpr(context, node->u.d_assign.aexp);
+ 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);
return 0;
}
- case NT_SEQ:
- if (interp_ast(context, node->u.d_seq.stm1)) return -1;
- if (interp_ast(context, node->u.d_seq.stm2)) return -1;
+ 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;
return 0;
- case NT_IF:
- if (eval_bexpr(context, node->u.d_if.bexp)) return interp_ast(context, node->u.d_if.stm1);
- else return interp_ast(context, node->u.d_if.stm2);
- case NT_WHILE:
- while (eval_bexpr(context, node->u.d_while.bexp)) {
- if (interp_ast(context, node->u.d_while.stm)) return -1;
+ 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);
+ 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;
}
return 0;
- case NT_LET: {
- char *name = node->u.d_let.var->u.d_var.name;
+ 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 new_val = eval_aexpr(context, node->u.d_let.aexp);
+ int new_val = eval_aexpr(context, node->data.let_stmt.aexpr);
context_set_var(context, name, new_val);
- int ret = interp_ast(context, node->u.d_let.stm);
+ int ret = interp_ast(context, node->data.let_stmt.body_stmt);
context_set_var(context, name, old_val);
return ret;
}
- case NT_PROCDECL: {
- char *name = node->u.d_procdecl.name;
- ASTNode *procdecl_old = context_get_proc(context, name);
+ 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) {
fprintf(stderr, "Error: procedure %s already defined\n", name);
return -1;
}
- ASTNode *procdecl = ast_clone(node);
+ IMP_ASTNode *procdecl = imp_ast_clone(node);
context_set_proc(context, name, procdecl);
return 0;
}
- case NT_PROCCALL: {
+ case IMP_AST_NT_PROCCALL: {
return interp_proccall(context, node);
}
default: assert(0);
@@ -388,16 +388,16 @@ int interp_file (Context *context, const char *path) {
}
yyrestart(yyin);
if (yyparse()) {
- ast_free(ast_root);
+ imp_ast_free(ast_root);
fclose(yyin);
return -1;
}
if (interp_ast(context, ast_root)) {
- ast_free(ast_root);
+ imp_ast_free(ast_root);
fclose(yyin);
return -1;
}
- ast_free(ast_root);
+ imp_ast_free(ast_root);
fclose(yyin);
return 0;
}
@@ -405,12 +405,12 @@ int interp_file (Context *context, const char *path) {
int interp_str (Context *context, const char *str) {
YY_BUFFER_STATE buf = yy_scan_string(str);
if (yyparse()) {
- ast_free(ast_root);
+ imp_ast_free(ast_root);
yy_delete_buffer(buf);
return -1;
}
if (interp_ast(context, ast_root)) {
- ast_free(ast_root);
+ imp_ast_free(ast_root);
yy_delete_buffer(buf);
return -1;
}
@@ -425,12 +425,12 @@ int print_ast_file (const char *path) {
}
yyrestart(yyin);
if (yyparse()) {
- ast_free(ast_root);
+ imp_ast_free(ast_root);
fclose(yyin);
return -1;
}
ast_print(ast_root, 0);
- ast_free(ast_root);
+ imp_ast_free(ast_root);
fclose(yyin);
return 0;
} \ No newline at end of file
diff --git a/src/parser.y b/src/parser.y
index 164b3cc..5952aa9 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -6,7 +6,7 @@ extern char *yytext;
extern int yylineno;
extern int yylex();
-ASTNode *ast_root;
+IMP_ASTNode *ast_root;
void yyerror(const char *s) {
fprintf(stderr, "Parse error at token \"%s\", line %d: %s\n", yytext, yylineno, s);
@@ -15,10 +15,10 @@ void yyerror(const char *s) {
%union {
- int num;
- char *id;
- struct ASTNode *node;
- struct ASTNodeList *node_list;
+ int num;
+ char *id;
+ struct IMP_ASTNode *node;
+ struct IMP_ASTNodeList *node_list;
}
%start prog
@@ -47,23 +47,23 @@ prog : stm
;
stm : T_SKIP
- { $$ = ast_skip(); }
+ { $$ = imp_ast_skip(); }
| var T_ASSIGN aexp
- { $$ = ast_assign($1, $3); }
+ { $$ = imp_ast_assign($1, $3); }
| T_LPAREN stm T_SEM stm T_RPAREN
- { $$ = ast_seq($2, $4); }
+ { $$ = imp_ast_seq($2, $4); }
| stm T_SEM stm
- { $$ = ast_seq($1, $3); }
+ { $$ = imp_ast_seq($1, $3); }
| stm T_SEM
{ $$ = $1; }
| T_IF bexp T_THEN stm T_ELSE stm T_END
- { $$ = ast_if($2, $4, $6); }
+ { $$ = imp_ast_if($2, $4, $6); }
| T_IF bexp T_THEN stm T_END
- { $$ = ast_if($2, $4, ast_skip()); }
+ { $$ = imp_ast_if($2, $4, imp_ast_skip()); }
| T_WHILE bexp T_DO stm T_END
- { $$ = ast_while($2, $4); }
+ { $$ = imp_ast_while($2, $4); }
| T_VAR var T_ASSIGN aexp T_IN stm T_END
- { $$ = ast_let($2, $4, $6); }
+ { $$ = imp_ast_let($2, $4, $6); }
| procd
{ $$ = $1; }
| procc
@@ -71,62 +71,62 @@ stm : T_SKIP
;
var : T_ID
- { $$ = ast_var($1); }
+ { $$ = imp_ast_var($1); }
;
aexp : aexp T_PLUS aexp
- { $$ = ast_aop(AOP_ADD, $1, $3); }
+ { $$ = imp_ast_aop(IMP_AST_AOP_ADD, $1, $3); }
| aexp T_MINUS aexp
- { $$ = ast_aop(AOP_SUB, $1, $3); }
+ { $$ = imp_ast_aop(IMP_AST_AOP_SUB, $1, $3); }
| aexp T_STAR aexp
- { $$ = ast_aop(AOP_MUL, $1, $3); }
+ { $$ = imp_ast_aop(IMP_AST_AOP_MUL, $1, $3); }
| T_MINUS aexp %prec T_UMINUS
- { $$ = ast_aop(AOP_SUB, ast_int(0), $2); }
+ { $$ = imp_ast_aop(IMP_AST_AOP_SUB, imp_ast_int(0), $2); }
| T_LPAREN aexp T_RPAREN
{ $$ = $2; }
| var
{ $$ = $1; }
| T_NUM
- { $$ = ast_int($1); }
+ { $$ = imp_ast_int($1); }
;
bexp : bexp T_OR bexp
- { $$ = ast_bop(BOP_OR, $1, $3); }
+ { $$ = imp_ast_bop(IMP_AST_BOP_OR, $1, $3); }
| bexp T_AND bexp
- { $$ = ast_bop(BOP_AND, $1, $3); }
+ { $$ = imp_ast_bop(IMP_AST_BOP_AND, $1, $3); }
| T_NOT bexp
- { $$ = ast_not($2); }
+ { $$ = imp_ast_not($2); }
| aexp T_EQ aexp
- { $$ = ast_rop(ROP_EQ, $1, $3); }
+ { $$ = imp_ast_rop(IMP_AST_ROP_EQ, $1, $3); }
| aexp T_NE aexp
- { $$ = ast_rop(ROP_NE, $1, $3); }
+ { $$ = imp_ast_rop(IMP_AST_ROP_NE, $1, $3); }
| aexp T_LE aexp
- { $$ = ast_rop(ROP_LE, $1, $3); }
+ { $$ = imp_ast_rop(IMP_AST_ROP_LE, $1, $3); }
| aexp T_LT aexp
- { $$ = ast_rop(ROP_LT, $1, $3); }
+ { $$ = imp_ast_rop(IMP_AST_ROP_LT, $1, $3); }
| aexp T_GE aexp
- { $$ = ast_rop(ROP_GE, $1, $3); }
+ { $$ = imp_ast_rop(IMP_AST_ROP_GE, $1, $3); }
| aexp T_GT aexp
- { $$ = ast_rop(ROP_GT, $1, $3); }
+ { $$ = imp_ast_rop(IMP_AST_ROP_GT, $1, $3); }
| T_LPAREN bexp T_RPAREN
{ $$ = $2; }
| T_TRUE
- { $$ = ast_rop(ROP_EQ, ast_int(1), ast_int(1)); }
+ { $$ = imp_ast_rop(IMP_AST_ROP_EQ, imp_ast_int(1), imp_ast_int(1)); }
| T_FALSE
- { $$ = ast_rop(ROP_EQ, ast_int(0), ast_int(1)); }
+ { $$ = imp_ast_rop(IMP_AST_ROP_EQ, imp_ast_int(0), imp_ast_int(1)); }
;
args : var
- { $$ = ast_node_list($1, NULL); }
+ { $$ = imp_ast_list($1, NULL); }
| args T_COM var
- { $$ = ast_node_list($3, $1); }
+ { $$ = imp_ast_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); }
+ { $$ = imp_ast_procdecl($2, $4, $6, $9); }
;
procc : T_ID T_LPAREN args T_SEM args T_RPAREN
- { $$ = ast_proccall($1, $3, $5); }
+ { $$ = imp_ast_proccall($1, $3, $5); }
;
%%