mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-07 08:08:50 +00:00
Manually implement tail-recursion for parse_if_stmt
This commit is contained in:
+20
-10
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user