Manually implement tail-recursion for parse_if_stmt

This commit is contained in:
gingerBill
2024-08-24 13:16:55 +01:00
parent a4cc207022
commit b6d9a0c32e
2 changed files with 20 additions and 12 deletions
+20 -10
View File
@@ -4532,12 +4532,10 @@ gb_internal Ast *parse_if_stmt(AstFile *f) {
return ast_bad_stmt(f, f->curr_token, f->curr_token); return ast_bad_stmt(f, f->curr_token, f->curr_token);
} }
if (f->recursion_depth_else_if > 256) { Ast *top_if_stmt = nullptr;
syntax_error(f->curr_token, "if-else chain recursion depth limit hit. Consider using a 'switch' statement instead or refactor the code to not require a large if-else chain");
f->recursion_depth_else_if = 0;
return ast_bad_stmt(f, f->curr_token, f->curr_token);
}
Ast *prev_if_stmt = nullptr;
if_else_chain:;
Token token = expect_token(f, Token_if); Token token = expect_token(f, Token_if);
Ast *init = nullptr; Ast *init = nullptr;
Ast *cond = nullptr; Ast *cond = nullptr;
@@ -4579,14 +4577,24 @@ gb_internal Ast *parse_if_stmt(AstFile *f) {
ignore_strict_style = true; ignore_strict_style = true;
} }
skip_possible_newline_for_literal(f, ignore_strict_style); skip_possible_newline_for_literal(f, ignore_strict_style);
Ast *curr_if_stmt = ast_if_stmt(f, token, init, cond, body, nullptr);
if (top_if_stmt == nullptr) {
top_if_stmt = curr_if_stmt;
}
if (prev_if_stmt != nullptr) {
prev_if_stmt->IfStmt.else_stmt = curr_if_stmt;
}
if (f->curr_token.kind == Token_else) { if (f->curr_token.kind == Token_else) {
Token else_token = expect_token(f, Token_else); Token else_token = expect_token(f, Token_else);
switch (f->curr_token.kind) { switch (f->curr_token.kind) {
case Token_if: case Token_if:
f->recursion_depth_else_if += 1; // NOTE(bill): Instead of relying on recursive descent for an if-else chain
else_stmt = parse_if_stmt(f); // we can just inline the tail-recursion manually with a simple loop like
f->recursion_depth_else_if -= 1; // construct using a `goto`
break; prev_if_stmt = curr_if_stmt;
goto if_else_chain;
case Token_OpenBrace: case Token_OpenBrace:
else_stmt = parse_block_stmt(f, false); else_stmt = parse_block_stmt(f, false);
break; break;
@@ -4601,7 +4609,9 @@ gb_internal Ast *parse_if_stmt(AstFile *f) {
} }
} }
return ast_if_stmt(f, token, init, cond, body, else_stmt); curr_if_stmt->IfStmt.else_stmt = else_stmt;
return top_if_stmt;
} }
gb_internal Ast *parse_when_stmt(AstFile *f) { gb_internal Ast *parse_when_stmt(AstFile *f) {
-2
View File
@@ -120,8 +120,6 @@ struct AstFile {
bool allow_type; bool allow_type;
bool in_when_statement; bool in_when_statement;
isize recursion_depth_else_if;
isize total_file_decl_count; isize total_file_decl_count;
isize delayed_decl_count; isize delayed_decl_count;
Slice<Ast *> decls; Slice<Ast *> decls;