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
This commit is contained in:
Jose Luis Montañes Ojados
2026-02-16 05:12:28 +01:00
parent 84b3abbfda
commit 65220f88c6
5 changed files with 64 additions and 11 deletions

View File

@@ -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;