From 1736db5f0f2ab558ac4a0c67b1a324b923ef59ed Mon Sep 17 00:00:00 2001 From: "Justin J. Meza" Date: Thu, 2 Sep 2010 01:37:20 -0700 Subject: [PATCH] Implemented variable deallocation --- interpreter.c | 122 ++++++++++++++++-- parser.c | 71 ++++++++++ parser.h | 37 ++++-- .../6-Variables/9-Deallocation/test.lol | 17 +++ .../6-Variables/9-Deallocation/test.out | 5 + .../6-Variables/9-Deallocation/test.readme | 1 + tokenizer.h | 2 + 7 files changed, 235 insertions(+), 20 deletions(-) create mode 100644 test/1.3-Tests/6-Variables/9-Deallocation/test.lol create mode 100644 test/1.3-Tests/6-Variables/9-Deallocation/test.out create mode 100644 test/1.3-Tests/6-Variables/9-Deallocation/test.readme diff --git a/interpreter.c b/interpreter.c index a96c587..ab31778 100644 --- a/interpreter.c +++ b/interpreter.c @@ -281,7 +281,8 @@ void deleteScopeObject(ScopeObject *scope) /**< [in,out] The ScopeObject structu * * \see getLocalScopeValue(ScopeObject *, IdentifierNode *) * \see createScopeValue(ScopeObject *, IdentifierNode *) - * \see updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *) */ + * \see updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *) + * \see deleteScopeValue(ScopeObject *, IdentifierNode *) */ ValueObject *getScopeValue(ScopeObject *scope, /**< [in] The ScopeObject structure to check. */ IdentifierNode *target) /**< [in] The name of the value to find. */ { @@ -312,7 +313,8 @@ ValueObject *getScopeValue(ScopeObject *scope, /**< [in] The ScopeObject str * * \see getScopeValue(ScopeObject *, IdentifierNode *) * \see createScopeValue(ScopeObject *, IdentifierNode *) - * \see updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *) */ + * \see updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *) + * \see deleteScopeValue(ScopeObject *, IdentifierNode *) */ ValueObject *getLocalScopeValue(ScopeObject *scope, /**< [in] The ScopeObject structure to check. */ IdentifierNode *target) /**< [in] The name of the value to find. */ { @@ -339,7 +341,8 @@ ValueObject *getLocalScopeValue(ScopeObject *scope, /**< [in] The ScopeObjec * * \see getScopeValue(ScopeObject *, IdentifierNode *) * \see getLocalScopeValue(ScopeObject *, IdentifierNode *) - * \see updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *) */ + * \see updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *) + * \see deleteScopeValue(ScopeObject *, IdentifierNode *) */ ValueObject *createScopeValue(ScopeObject *scope, /**< [in,out] The ScopeObject structure to add a value to. */ IdentifierNode *target) /**< [in] The name of the value to add. */ { @@ -385,7 +388,8 @@ ValueObject *createScopeValue(ScopeObject *scope, /**< [in,out] The ScopeObj * * \see getScopeValue(ScopeObject *, IdentifierNode *) * \see getLocalScopeValue(ScopeObject *, IdentifierNode *) - * \see createScopeValue(ScopeObject *, IdentifierNode *) */ + * \see createScopeValue(ScopeObject *, IdentifierNode *) + * \see deleteScopeValue(ScopeObject *, IdentifierNode *) */ ValueObject *updateScopeValue(ScopeObject *scope, /**< [in,out] A pointer to the ScopeObject structure to update. */ IdentifierNode *target, /**< [in] A pointer to the IdentifierNode structure containing the name of the value to update. */ ValueObject *value) /**< [in] A pointer to the ValueObject structure containing the value to copy for the update. */ @@ -412,6 +416,61 @@ ValueObject *updateScopeValue(ScopeObject *scope, /**< [in,out] A pointer to return NULL; } +/** Deletes a ValueObject structure named by an IdentifierNode structure in a + * ScopeObject structure. + * + * \pre \a scope was created by createScopeObject(ScopeObject *) and contains + * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and + * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). + * \pre \a target was created by createIdentifierNode(char *). + * + * \see getScopeValue(ScopeObject *, IdentifierNode *) + * \see getLocalScopeValue(ScopeObject *, IdentifierNode *) + * \see createScopeValue(ScopeObject *, IdentifierNode *) + * \see updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *) */ +void deleteScopeValue(ScopeObject *scope, /**< [in,out] A pointer to the ScopeObject structure to delete from. */ + IdentifierNode *target) /**< [in] A pointer to the IdentifierNode structure containing the name of the value to delete. */ +{ + ScopeObject *current = scope; + /* Traverse upwards through scopes */ + do { + unsigned int n; + /* Check for existing value in current scope */ + for (n = 0; n < current->numvals; n++) { + if (!strcmp(current->names[n]->image, target->image)) { + unsigned int i; + unsigned int newnumvals = scope->numvals - 1; + void *mem1 = NULL, *mem2 = NULL; + /* Don't delete anything in the names table + * because it's just pointers to IdentifierNode + * structures in the parse tree. */ + /* Wipe out the value */ + deleteValueObject(current->values[n]); + /* Reorder the tables */ + for (i = n; i < current->numvals - 1; i++) { + current->names[i] = current->names[i + 1]; + current->values[i] = current->values[i + 1]; + } + /* Resize the tables */ + mem1 = realloc(scope->names, sizeof(IdentifierNode *) * newnumvals); + if (!mem1) { + perror("realloc"); + return; + } + mem2 = realloc(scope->values, sizeof(ValueObject *) * newnumvals); + if (!mem2) { + perror("realloc"); + return; + } + scope->names = mem1; + scope->values = mem2; + scope->numvals = newnumvals; + return; + } + } + } while ((current = current->parent)); +} + /** Checks if a string of characters follows the format for a number. * * \retval 0 The string of characters is not a number. @@ -2504,6 +2563,7 @@ ValueObject *interpretExprNode(ExprNode *node, /**< [in] A pointer to an Exp * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) + * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ ReturnObject *interpretCastStmtNode(StmtNode *node, /**< [in] A pointer to the StmtNode structure containing the CastStmtNode structure to interpret. */ @@ -2562,7 +2622,8 @@ ReturnObject *interpretCastStmtNode(StmtNode *node, /**< [in] A pointer to t * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) - * \see interpretlFuncDefStmtNode(StmtNode *, ScopeObject *) + * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) + * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ ReturnObject *interpretPrintStmtNode(StmtNode *node, /**< [in] A pointer to a StmtNode structure containing the PrintStmtNode structure to interpret. */ ScopeObject *scope) /**< [in] A pointer to the ScopeObject structure to evaluate \a node under. */ @@ -2607,7 +2668,8 @@ ReturnObject *interpretPrintStmtNode(StmtNode *node, /**< [in] A pointer to * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) - * \see interpretlFuncDefStmtNode(StmtNode *, ScopeObject *) + * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) + * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ ReturnObject *interpretInputStmtNode(StmtNode *node, /**< [in] A pointer to a StmtNode structure containing an InputStmtNode structure to interpret. */ ScopeObject *scope) /**< [in,out] A pointer to the ScopeObject structure to evaluate \a node under. */ @@ -2672,6 +2734,7 @@ ReturnObject *interpretInputStmtNode(StmtNode *node, /**< [in] A pointer to * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) + * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ ReturnObject *interpretAssignmentStmtNode(StmtNode *node, /**< [in] A pointer to a StmtNode structure containing the AssignmentStmtNode structure to interpret. */ @@ -2708,6 +2771,7 @@ ReturnObject *interpretAssignmentStmtNode(StmtNode *node, /**< [in] A pointe * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) + * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ ReturnObject *interpretDeclarationStmtNode(StmtNode *node, /**< [in] A pointer to a StmtNode structure containing the DeclarationStmtNode structure to interpret. */ @@ -2776,7 +2840,8 @@ ReturnObject *interpretDeclarationStmtNode(StmtNode *node, /**< [in] A point * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) - * \see interpretlFuncDefStmtNode(StmtNode *, ScopeObject *) + * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) + * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ ReturnObject *interpretIfThenElseStmtNode(StmtNode *node, /**< [in] A pointer to a StmtNode structure containing the IfThenElseStmtNode structure to interpret. */ ScopeObject *scope) /**< [in,out] A pointer to the ScopeObject structure to evaluate \a node under. */ @@ -2867,6 +2932,7 @@ ReturnObject *interpretIfThenElseStmtNode(StmtNode *node, /**< [in] A pointe * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) + * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ ReturnObject *interpretSwitchStmtNode(StmtNode *node, /**< [in] A pointer to the StmtNode structure containing the SwitchStmtNode structure to interpret. */ @@ -2965,6 +3031,7 @@ ReturnObject *interpretSwitchStmtNode(StmtNode *node, /**< [in] A pointer to * \see interpretSwitchStmtNode(StmtNode *, ScopeObject *) * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) + * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) * \see interpretlFuncDefStmtNode(StmtNode *, ScopeObject *) * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ ReturnObject *interpretBreakStmtNode(StmtNode *node, /**< Not used (see note). */ @@ -2997,6 +3064,7 @@ ReturnObject *interpretBreakStmtNode(StmtNode *node, /**< Not used (see note * \see interpretSwitchStmtNode(StmtNode *, ScopeObject *) * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) + * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ ReturnObject *interpretReturnStmtNode(StmtNode *node, /**< [in] A pointer to the StmtNode structure containing the ReturnStmtNode structure to interpret. */ @@ -3031,6 +3099,7 @@ ReturnObject *interpretReturnStmtNode(StmtNode *node, /**< [in] A pointer to * \see interpretSwitchStmtNode(StmtNode *, ScopeObject *) * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) + * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ ReturnObject *interpretLoopStmtNode(StmtNode *node, /**< [in] A pointer to the StmtNode structure containing the LoopStmtNode structure to interpret. */ @@ -3118,6 +3187,40 @@ ReturnObject *interpretLoopStmtNode(StmtNode *node, /**< [in] A pointer to t return createReturnObject(RT_DEFAULT, NULL); } +/** Interprets a deallocation statement. + * + * \pre \a node was created by createStmtNode(StmtType type, void *stmt) where + * \a type is ST_DEALLOCATION and \a stmt was created by createDeallocationStmtNode(IdentifierNode *). + * \pre \a scope was created by createScopeObject(ScopeObject *) and contains + * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and + * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). + * + * \return A pointer to a ReturnObject structure with the default return value. + * + * \retval NULL An error occurred during interpretation. + * + * \see interpretCastStmtNode(StmtNode *, ScopeObject *) + * \see interpretPrintStmtNode(StmtNode *, ScopeObject *) + * \see interpretInputStmtNode(StmtNode *, ScopeObject *) + * \see interpretDeclarationStmtNode(StmtNode *, ScopeObject *) + * \see interpretIfThenElseStmtNode(StmtNode *, ScopeObject *) + * \see interpretSwitchStmtNode(StmtNode *, ScopeObject *) + * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) + * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) + * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) + * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) + * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ +ReturnObject *interpretDeallocationStmtNode(StmtNode *node, /**< [in] A pointer to a StmtNode structure containing the DeallocationStmtNode structure to interpret. */ + ScopeObject *scope) /**< [in,out] A pointer to the ScopeObject structure to evaluate \a node under. */ +{ + DeallocationStmtNode *stmt = (DeallocationStmtNode *)node->stmt; + if (!updateScopeValue(scope, stmt->target, NULL)) return NULL; + /* If we want to completely remove the variable, use: + deleteScopeValue(scope, stmt->target); + */ + return createReturnObject(RT_DEFAULT, NULL); +} + /** Interprets a function definition statement. * * \pre \a node was created by createStmtNode(StmtType type, void *stmt) where @@ -3144,6 +3247,7 @@ ReturnObject *interpretLoopStmtNode(StmtNode *node, /**< [in] A pointer to t * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) + * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ ReturnObject *interpretFuncDefStmtNode(StmtNode *node, /**< Not used (see note). */ ScopeObject *scope) /**< Not used (see note). */ @@ -3176,6 +3280,7 @@ ReturnObject *interpretFuncDefStmtNode(StmtNode *node, /**< Not used (see no * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) + * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) */ ReturnObject *interpretExprStmtNode(StmtNode *node, /**< [in] A pointer to a StmtNode structure containing the ExprNode structure to interpret. */ ScopeObject *scope) /**< [in,out] A pointer to the ScopeObject structure to evaluate \a node under. */ @@ -3190,7 +3295,7 @@ ReturnObject *interpretExprStmtNode(StmtNode *node, /**< [in] A pointer to a /* A jump table for statements. The index of a function in the table is given * by its its index in the enumerated StmtType type. */ -static ReturnObject *(*StmtJumpTable[12])(StmtNode *, ScopeObject *) = { +static ReturnObject *(*StmtJumpTable[13])(StmtNode *, ScopeObject *) = { interpretCastStmtNode, interpretPrintStmtNode, interpretInputStmtNode, @@ -3201,6 +3306,7 @@ static ReturnObject *(*StmtJumpTable[12])(StmtNode *, ScopeObject *) = { interpretBreakStmtNode, interpretReturnStmtNode, interpretLoopStmtNode, + interpretDeallocationStmtNode, interpretFuncDefStmtNode, interpretExprStmtNode }; diff --git a/parser.c b/parser.c index 8592123..dfcce17 100644 --- a/parser.c +++ b/parser.c @@ -488,6 +488,11 @@ void deleteStmtNode(StmtNode *node) /**< [in, out] A pointer to the StmtNode str deleteLoopStmtNode(stmt); break; } + case ST_DEALLOCATION: { + DeallocationStmtNode *stmt = (DeallocationStmtNode *)node->stmt; + deleteDeallocationStmtNode(stmt); + break; + } case ST_EXPR: { ExprNode *expr = (ExprNode *)node->stmt; deleteExprNode(expr); @@ -949,6 +954,42 @@ void deleteLoopStmtNode(LoopStmtNode *node) /**< [in,out] A pointer to the LoopS free(node); } +/** Creates a DeallocationStmtNode structure. + * + * \pre \a target was created by createIdentifierNode(char *). + * + * \return A pointer to a DeallocationStmtNode structure with the desired + * properties. + * + * \retval NULL malloc was unable to allocate memory. + * + * \see deleteDeallocationStmtNode(DeallocationStmtNode *) */ +DeallocationStmtNode *createDeallocationStmtNode(IdentifierNode *target) /**< [in] A pointer to the name of the variable. */ +{ + DeallocationStmtNode *p = malloc(sizeof(DeallocationStmtNode)); + if (!p) { + perror("malloc"); + return NULL; + } + p->target = target; + return p; +} + +/** Deletes a DeallocationStmtNode structure. + * + * \pre \a node was created by createDeallocationStmtNode(IdentifierNode *). + * + * \post The memory at \a node and any of its associated members will be + * freed. + * + * \see createDeallocationStmtNode(IdentifierNode *) */ +void deleteDeallocationStmtNode(DeallocationStmtNode *node) /**< [in,out] A pointer to the DeallocationStmtNode structure to be deleted. */ +{ + if (!node) return; + deleteIdentifierNode(node->target); + free(node); +} + /** Creates a FuncDefStmtNode structure. * * \pre \a scope was created by createIdentifierNode(char *). @@ -2806,6 +2847,36 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p return NULL; } } + /* Deallocation */ + else if (nextToken(&tokens, TT_RNOOB)) { + IdentifierNode *target = NULL; + DeallocationStmtNode *stmt = NULL; +#ifdef DEBUG + debug("ST_DEALLOCATION"); +#endif + target = parseIdentifierNode(&tokens); + if (!target) return NULL; + if (!acceptToken(&tokens, TT_RNOOB)) { + error("expected R NOOB", tokens); + deleteIdentifierNode(target); + return NULL; + } + if (!acceptToken(&tokens, TT_NEWLINE)) { + error("expected end of statement", tokens); + deleteIdentifierNode(target); + return NULL; + } + stmt = createDeallocationStmtNode(target); + if (!stmt) { + deleteIdentifierNode(target); + return NULL; + } + ret = createStmtNode(ST_DEALLOCATION, stmt); + if (!ret) { + deleteDeallocationStmtNode(stmt); + return NULL; + } + } /* Function definition */ else if (acceptToken(&tokens, TT_HOWDUZ)) { IdentifierNode *scope = NULL; diff --git a/parser.h b/parser.h index 689e530..3819da7 100644 --- a/parser.h +++ b/parser.h @@ -200,18 +200,19 @@ typedef struct { /** Denotes the type of statement a StmtNode stores. */ typedef enum { - ST_CAST, /**< A CastStmtNode structure. */ - ST_PRINT, /**< A PrintStmtNode structure. */ - ST_INPUT, /**< An InputStmtNode structure. */ - ST_ASSIGNMENT, /**< An AssignmentStmtNode structure. */ - ST_DECLARATION, /**< A DeclarationStmtNode structure. */ - ST_IFTHENELSE, /**< An IfThenElseStmtNode structure. */ - ST_SWITCH, /**< A SwitchStmtNode structure. */ - ST_BREAK, /**< A break statement (no structure is needed for this type of statement). */ - ST_RETURN, /**< A ReturnStmtNode structure. */ - ST_LOOP, /**< A LoopStmtNode structure. */ - ST_FUNCDEF, /**< A FuncDefStmtNode structure. */ - ST_EXPR /**< An ExprNode structure. */ + ST_CAST, /**< A CastStmtNode structure. */ + ST_PRINT, /**< A PrintStmtNode structure. */ + ST_INPUT, /**< An InputStmtNode structure. */ + ST_ASSIGNMENT, /**< An AssignmentStmtNode structure. */ + ST_DECLARATION, /**< A DeclarationStmtNode structure. */ + ST_IFTHENELSE, /**< An IfThenElseStmtNode structure. */ + ST_SWITCH, /**< A SwitchStmtNode structure. */ + ST_BREAK, /**< A break statement (no structure is needed for this type of statement). */ + ST_RETURN, /**< A ReturnStmtNode structure. */ + ST_LOOP, /**< A LoopStmtNode structure. */ + ST_DEALLOCATION, /**< A DeallocationStmtNode structure. */ + ST_FUNCDEF, /**< A FuncDefStmtNode structure. */ + ST_EXPR /**< An ExprNode structure. */ } StmtType; /** Stores a statement. A statement is a unit of code which can be executed by @@ -466,6 +467,15 @@ typedef struct { BlockNode *body; /**< A pointer to the block of code to be executed with each iteration of the loop. */ } LoopStmtNode; +/** Deallocates a variable. This means freeing the memory and structures used + * by the variable. + * + * \see createDeallocationStmtNode(IdentifierNode *) + * \see deleteDeallocationStmtNode(DeallocationStmtNode *) */ +typedef struct { + IdentifierNode *target; /**< A pointer to the name of the variable. */ +} DeallocationStmtNode; + /** Stores a cast expression. A cast expression evaluates an expression and * casts it to a particular type. * @@ -571,6 +581,9 @@ void deleteReturnStmtNode(ReturnStmtNode *); LoopStmtNode *createLoopStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *, ExprNode *, BlockNode *); void deleteLoopStmtNode(LoopStmtNode *); +DeallocationStmtNode *createDeallocationStmtNode(IdentifierNode *); +void deleteDeallocationStmtNode(DeallocationStmtNode *); + FuncDefStmtNode *createFuncDefStmtNode(IdentifierNode *, IdentifierNode *, IdentifierNodeList *, BlockNode *); void deleteFuncDefStmtNode(FuncDefStmtNode *); diff --git a/test/1.3-Tests/6-Variables/9-Deallocation/test.lol b/test/1.3-Tests/6-Variables/9-Deallocation/test.lol new file mode 100644 index 0000000..4a13111 --- /dev/null +++ b/test/1.3-Tests/6-Variables/9-Deallocation/test.lol @@ -0,0 +1,17 @@ +HAI 1.3 + I HAS A var1 + I HAS A var2 ITZ WIN + I HAS A var3 ITZ 1 + I HAS A var4 ITZ 2.345 + I HAS A var5 ITZ "Lorem ipsum dolor sit." + var1 R NOOB + var2 R NOOB + var3 R NOOB + var4 R NOOB + var5 R NOOB + VISIBLE SUM OF 0 AN NOT var1 + VISIBLE SUM OF 0 AN NOT var2 + VISIBLE SUM OF 0 AN NOT var3 + VISIBLE SUM OF 0 AN NOT var4 + VISIBLE SUM OF 0 AN NOT var5 +KTHXBYE diff --git a/test/1.3-Tests/6-Variables/9-Deallocation/test.out b/test/1.3-Tests/6-Variables/9-Deallocation/test.out new file mode 100644 index 0000000..627e109 --- /dev/null +++ b/test/1.3-Tests/6-Variables/9-Deallocation/test.out @@ -0,0 +1,5 @@ +1 +1 +1 +1 +1 diff --git a/test/1.3-Tests/6-Variables/9-Deallocation/test.readme b/test/1.3-Tests/6-Variables/9-Deallocation/test.readme new file mode 100644 index 0000000..abf9835 --- /dev/null +++ b/test/1.3-Tests/6-Variables/9-Deallocation/test.readme @@ -0,0 +1 @@ +This test checks that variables can be deallocated correctly. diff --git a/tokenizer.h b/tokenizer.h index 10f6165..fcb97b7 100644 --- a/tokenizer.h +++ b/tokenizer.h @@ -44,6 +44,7 @@ typedef enum { TT_HASA, TT_ITZA, TT_ITZ, + TT_RNOOB, TT_R, TT_ANYR, TT_AN, @@ -111,6 +112,7 @@ static const char *keywords[] = { "HAS A", /* TT_HASA */ "ITZ A", /* TT_ITZA */ "ITZ", /* TT_ITZ */ + "R NOOB", /* TT_RNOOB */ "R", /* TT_R */ "AN YR", /* TT_ANYR */ "AN", /* TT_AN */