diff options
author | Flavian Kaufmann <flavian@flaviankaufmann.ch> | 2025-05-23 11:25:29 +0200 |
---|---|---|
committer | Flavian Kaufmann <flavian@flaviankaufmann.ch> | 2025-05-23 11:25:29 +0200 |
commit | de59dbd1773dff06051b7b604977bcb2803ada4f (patch) | |
tree | 60be4de19aa7be4d4d99136c2bfbb824edfa2d90 | |
parent | 987a7c553701251d48b11a2243892ecd74ce6c4d (diff) | |
download | imp-de59dbd1773dff06051b7b604977bcb2803ada4f.tar.gz imp-de59dbd1773dff06051b7b604977bcb2803ada4f.zip |
[cleanup] ast
-rw-r--r-- | include/ast.h | 269 | ||||
-rw-r--r-- | include/hashmap.h | 3 | ||||
-rw-r--r-- | include/interpreter.h | 2 | ||||
-rw-r--r-- | src/ast.c | 337 | ||||
-rw-r--r-- | src/hashmap.c | 10 | ||||
-rw-r--r-- | src/interpreter.c | 288 | ||||
-rw-r--r-- | src/parser.y | 68 |
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); @@ -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); } ; %% |