diff options
author | Flavian Kaufmann <flavian@flaviankaufmann.ch> | 2025-05-20 14:18:30 +0200 |
---|---|---|
committer | Flavian Kaufmann <flavian@flaviankaufmann.ch> | 2025-05-20 14:18:30 +0200 |
commit | fbbe2f207a26b410d485c9dea07a22256a02d50b (patch) | |
tree | 164e2d30f43bd25ecc7c3f6ca4d49d1c30f4f1a7 /src | |
parent | 9cf524df8c94920d7c7058692f2f83a95a4006e0 (diff) | |
download | imp-fbbe2f207a26b410d485c9dea07a22256a02d50b.tar.gz imp-fbbe2f207a26b410d485c9dea07a22256a02d50b.zip |
local variables
Diffstat (limited to 'src')
-rw-r--r-- | src/ast.c | 9 | ||||
-rw-r--r-- | src/interpreter.c | 13 | ||||
-rw-r--r-- | src/lexer.l | 2 | ||||
-rw-r--r-- | src/parser.y | 4 |
4 files changed, 25 insertions, 3 deletions
@@ -88,6 +88,15 @@ ASTNode *ast_rop(ROp rop, ASTNode *aexp1, ASTNode *aexp2) { 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; + return node; +} + + void ast_free(ASTNode *node) { if (!node) return; switch (node->type) { diff --git a/src/interpreter.c b/src/interpreter.c index 93b1bdb..4449847 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -76,9 +76,9 @@ void exec_stmt(hashmap_t context, ASTNode *node) { case NT_SKIP: return; case NT_ASSIGN: { - char *var = node->u.d_assign.var->u.d_var.name; + char *name = node->u.d_assign.var->u.d_var.name; int val = eval_aexpr(context, node->u.d_assign.aexp); - context_set(context, var, val); + context_set(context, name, val); return; } case NT_SEQ: @@ -96,6 +96,15 @@ void exec_stmt(hashmap_t context, ASTNode *node) { exec_stmt(context, node->u.d_while.stm); } return; + case NT_LET: { + char *name = node->u.d_let.var->u.d_var.name; + int old_val = context_get(context, name); + int new_val = eval_aexpr(context, node->u.d_let.aexp); + context_set(context, name, new_val); + exec_stmt(context, node->u.d_let.stm); + context_set(context, name, old_val); + return; + } default: fprintf(stderr, "Bad stmt node %d\n", node->type); exit(EXIT_FAILURE); diff --git a/src/lexer.l b/src/lexer.l index c9aaff0..26ac229 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -17,6 +17,8 @@ WHITESPACE [ \t\r\n]+ "end" { return TOKEN_END; } "while" { return TOKEN_WHILE; } "do" { return TOKEN_DO; } +"var" { return TOKEN_VAR; } +"in" { return TOKEN_IN; } "(" { return TOKEN_LEFT_PARENTHESIS; } ")" { return TOKEN_RIGHT_PARENTHESIS; } diff --git a/src/parser.y b/src/parser.y index 9a94480..cb3544e 100644 --- a/src/parser.y +++ b/src/parser.y @@ -29,7 +29,7 @@ void yyerror(const char *s) { %token TOKEN_LEFT_PARENTHESIS TOKEN_RIGHT_PARENTHESIS %token TOKEN_SEMICOLON %token TOKEN_SKIP -%token TOKEN_IF TOKEN_THEN TOKEN_ELSE TOKEN_END TOKEN_WHILE TOKEN_DO +%token TOKEN_IF TOKEN_THEN TOKEN_ELSE TOKEN_END TOKEN_WHILE TOKEN_DO TOKEN_VAR TOKEN_IN %token TOKEN_PLUS TOKEN_MINUS TOKEN_MULTIPLY %token TOKEN_NOT TOKEN_OR TOKEN_AND %token TOKEN_EQUALS TOKEN_NOT_EQUALS TOKEN_LESS_THAN TOKEN_LESS_EQUAL TOKEN_GREATER_THAN TOKEN_GREATER_EQUAL @@ -54,6 +54,8 @@ statement : TOKEN_SKIP { $$ = ast_if($2, $4, $6); } | TOKEN_WHILE boolean_expression TOKEN_DO statement TOKEN_END { $$ = ast_while($2, $4); } + | TOKEN_VAR variable TOKEN_ASSIGN arithmetic_expression TOKEN_IN statement TOKEN_END + { $$ = ast_let($2, $4, $6); } ; variable : TOKEN_IDENTIFIER |