From 65220f88c630deef9784b1940291524a80d623dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Monta=C3=B1es=20Ojados?= Date: Mon, 16 Feb 2026 05:12:28 +0100 Subject: [PATCH] Add if statements, unary minus, and fix GC safe points - Lexer: recognize 'if' as keyword (TOK_IF) - Parser: add NODE_IF with if_statement union, parse if/cond/body, handle unary minus in parse_term as 0 - expr - Eval: add NODE_IF evaluation, move GC to NODE_BLOCK level to avoid destroying temporary values during sub-expression evaluation --- projects/if.j | 4 ++++ projects/while.j | 2 +- src/frontend/lexer.h | 2 ++ src/frontend/parser.h | 46 +++++++++++++++++++++++++++++++++++++++++++ src/vm/eval.h | 21 ++++++++++---------- 5 files changed, 64 insertions(+), 11 deletions(-) create mode 100644 projects/if.j diff --git a/projects/if.j b/projects/if.j new file mode 100644 index 0000000..6005f77 --- /dev/null +++ b/projects/if.j @@ -0,0 +1,4 @@ +x = 20 +if x < 10: + print x +print -300 \ No newline at end of file diff --git a/projects/while.j b/projects/while.j index 174f331..2888062 100644 --- a/projects/while.j +++ b/projects/while.j @@ -1,4 +1,4 @@ x = 0 -while x < 100000000: +while x < 10000000: x = x + 1 print x diff --git a/src/frontend/lexer.h b/src/frontend/lexer.h index f9f1c59..8cb22f7 100644 --- a/src/frontend/lexer.h +++ b/src/frontend/lexer.h @@ -135,6 +135,8 @@ Token *tokenize(const char *source, int *token_count) { tokens[count++] = make_token(TOK_PRINT, word); } else if (strcmp(word, "while") == 0) { tokens[count++] = make_token(TOK_WHILE, word); + } else if (strcmp(word, "if") == 0) { + tokens[count++] = make_token(TOK_IF, word); } else { tokens[count++] = make_token(TOK_ID, word); } diff --git a/src/frontend/parser.h b/src/frontend/parser.h index b104c10..bc99316 100644 --- a/src/frontend/parser.h +++ b/src/frontend/parser.h @@ -43,6 +43,10 @@ typedef struct ASTNode { struct ASTNode *cond; struct ASTNode *body; } while_loop; // NODE_WHILE + struct { + struct ASTNode *cond; + struct ASTNode *body; + } if_statement; // NODE_IF } data; } ASTNode; @@ -65,6 +69,15 @@ ASTNode *parse_term(Token *tokens) { node->data.string_val = tokens[pos].value; pos++; return node; + } else if (tokens[pos].type == TOK_MINUS) { + pos++; // consumir '-' + ASTNode *term = parse_term(tokens); + ASTNode *neg = make_node(NODE_BINOP); + neg->data.binop.op = '-'; + neg->data.binop.left = make_node(NODE_INT_LIT); + neg->data.binop.left->data.int_val = 0; + neg->data.binop.right = term; + return neg; } printf("ERROR: esperaba INT o ID, encontré tipo %d\n", tokens[pos].type); exit(1); @@ -135,6 +148,33 @@ ASTNode *parse_statement(Token *tokens) { node->data.while_loop.body = body; return node; } + + if (tokens[pos].type == TOK_IF) { + pos++; // consumir if + ASTNode *cond = parse_expr(tokens); + pos++; // consumir : + pos++; // consumir NEWLINE + pos++; // consumir INDENT + + // Parsear bloque de statements hasta DEDENT + ASTNode *body = make_node(NODE_BLOCK); + body->data.block.stmts = (ASTNode **)malloc(sizeof(ASTNode *) * 256); + body->data.block.count = 0; + while (tokens[pos].type != TOK_DEDENT) { + body->data.block.stmts[body->data.block.count++] = + parse_statement(tokens); + if (tokens[pos].type == TOK_NEWLINE) { + pos++; + } + } + pos++; // Consumir DEDENT + + ASTNode *node = make_node(NODE_IF); + node->data.while_loop.cond = cond; + node->data.while_loop.body = body; + return node; + } + printf("ERROR: statement inesperado\n"); exit(1); } @@ -215,6 +255,12 @@ void ast_print(ASTNode *node, const char *prefix, int is_last) { } break; + case NODE_IF: + printf("NODE_IF\n"); + ast_print(node->data.while_loop.cond, new_prefix, 0); + ast_print(node->data.while_loop.body, new_prefix, 1); + break; + default: printf("UNKNOWN\n"); break; diff --git a/src/vm/eval.h b/src/vm/eval.h index 688ed41..66b4b93 100644 --- a/src/vm/eval.h +++ b/src/vm/eval.h @@ -41,16 +41,8 @@ void env_set(Environment *env, const char *name, size_t value) { int step = 0; -size_t eval(ASTNode *node, Environment *env, void *allocator, int debug, int gc) { - - // Run GC - if (gc) { - size_t roots[256]; - for (int i = 0; i < env->count; i++) { - roots[i] = env->vars[i].value; - } - gc_collect(allocator, roots, env->count); - } +size_t eval(ASTNode *node, Environment *env, void *allocator, int debug, + int gc) { if (debug > 0) { step++; @@ -101,6 +93,15 @@ size_t eval(ASTNode *node, Environment *env, void *allocator, int debug, int gc) return val; } case NODE_BLOCK: + // Run GC + if (gc) { + size_t roots[256]; + for (int i = 0; i < env->count; i++) { + roots[i] = env->vars[i].value; + } + gc_collect(allocator, roots, env->count); + } + for (int i = 0; i < node->data.block.count; i++) eval(node->data.block.stmts[i], env, allocator, debug, gc); return 0;