astgen: fix rlExpr bugs for inline while/for labels, assign_destructure, and @-quoted identifiers
Fix three issues in the RL annotation pre-pass (rlExpr): 1. Label detection for `inline while`/`inline for` now accounts for the `keyword_inline` token before checking for `identifier colon`, matching upstream fullWhileComponents/fullForComponents logic. 2. `assign_destructure` now recurses into variable nodes and the value expression with RL_RI_NONE, matching upstream behavior instead of returning false without visiting sub-expressions. 3. `rlTokenIdentEqual` now handles @"..."-quoted identifiers by comparing the quoted content rather than stopping at the `@` character, which previously caused all @-quoted identifiers to compare as equal. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
54
astgen.c
54
astgen.c
@@ -9547,11 +9547,33 @@ static bool nodesNeedRlContains(const AstGenCtx* ag, uint32_t node) {
|
||||
}
|
||||
|
||||
// Compare two identifier tokens by their source text.
|
||||
// Handles both regular identifiers and @"..."-quoted identifiers.
|
||||
static bool rlTokenIdentEqual(
|
||||
const Ast* tree, uint32_t tok_a, uint32_t tok_b) {
|
||||
const char* src = tree->source;
|
||||
uint32_t a_start = tree->tokens.starts[tok_a];
|
||||
uint32_t b_start = tree->tokens.starts[tok_b];
|
||||
bool a_quoted = (src[a_start] == '@');
|
||||
bool b_quoted = (src[b_start] == '@');
|
||||
if (a_quoted != b_quoted)
|
||||
return false;
|
||||
if (a_quoted) {
|
||||
// Both are @"..."-quoted: skip '@"' prefix, compare up to '"'.
|
||||
uint32_t ai = a_start + 2;
|
||||
uint32_t bi = b_start + 2;
|
||||
for (;;) {
|
||||
char ca = src[ai];
|
||||
char cb = src[bi];
|
||||
if (ca == '"' && cb == '"')
|
||||
return true;
|
||||
if (ca == '"' || cb == '"')
|
||||
return false;
|
||||
if (ca != cb)
|
||||
return false;
|
||||
ai++;
|
||||
bi++;
|
||||
}
|
||||
}
|
||||
for (uint32_t i = 0;; i++) {
|
||||
char ca = src[a_start + i];
|
||||
char cb = src[b_start + i];
|
||||
@@ -9998,10 +10020,13 @@ static bool rlExpr(
|
||||
else_node = tree->extra_data.arr[nd.rhs + 2];
|
||||
}
|
||||
uint32_t main_tok = tree->nodes.main_tokens[node];
|
||||
uint32_t tok_i = main_tok;
|
||||
if (tok_i >= 1 && tree->tokens.tags[tok_i - 1] == TOKEN_KEYWORD_INLINE)
|
||||
tok_i = tok_i - 1;
|
||||
bool is_labeled
|
||||
= (main_tok >= 2 && tree->tokens.tags[main_tok - 1] == TOKEN_COLON
|
||||
&& tree->tokens.tags[main_tok - 2] == TOKEN_IDENTIFIER);
|
||||
uint32_t label_token = is_labeled ? main_tok - 2 : UINT32_MAX;
|
||||
= (tok_i >= 2 && tree->tokens.tags[tok_i - 1] == TOKEN_COLON
|
||||
&& tree->tokens.tags[tok_i - 2] == TOKEN_IDENTIFIER);
|
||||
uint32_t label_token = is_labeled ? tok_i - 2 : UINT32_MAX;
|
||||
|
||||
// Detect payload/error.
|
||||
uint32_t last_cond_tok = lastToken(tree, cond_node);
|
||||
@@ -10069,10 +10094,14 @@ static bool rlExpr(
|
||||
}
|
||||
|
||||
uint32_t main_tok = tree->nodes.main_tokens[node];
|
||||
bool is_labeled
|
||||
= (main_tok >= 2 && tree->tokens.tags[main_tok - 1] == TOKEN_COLON
|
||||
&& tree->tokens.tags[main_tok - 2] == TOKEN_IDENTIFIER);
|
||||
uint32_t label_token = is_labeled ? main_tok - 2 : UINT32_MAX;
|
||||
uint32_t for_tok_i = main_tok;
|
||||
if (for_tok_i >= 1
|
||||
&& tree->tokens.tags[for_tok_i - 1] == TOKEN_KEYWORD_INLINE)
|
||||
for_tok_i = for_tok_i - 1;
|
||||
bool is_labeled = (for_tok_i >= 2
|
||||
&& tree->tokens.tags[for_tok_i - 1] == TOKEN_COLON
|
||||
&& tree->tokens.tags[for_tok_i - 2] == TOKEN_IDENTIFIER);
|
||||
uint32_t label_token = is_labeled ? for_tok_i - 2 : UINT32_MAX;
|
||||
|
||||
for (uint32_t i = 0; i < num_inputs; i++) {
|
||||
uint32_t input = inputs[i];
|
||||
@@ -10646,8 +10675,15 @@ static bool rlExpr(
|
||||
case AST_NODE_AWAIT:
|
||||
(void)rlExpr(ag, nd.lhs, block, RL_RI_NONE);
|
||||
return false;
|
||||
case AST_NODE_ASSIGN_DESTRUCTURE:
|
||||
return false; // TODO if needed
|
||||
case AST_NODE_ASSIGN_DESTRUCTURE: {
|
||||
uint32_t extra_start = nd.lhs;
|
||||
uint32_t variable_count = tree->extra_data.arr[extra_start];
|
||||
for (uint32_t i = 0; i < variable_count; i++)
|
||||
(void)rlExpr(ag, tree->extra_data.arr[extra_start + 1 + i], block,
|
||||
RL_RI_NONE);
|
||||
(void)rlExpr(ag, nd.rhs, block, RL_RI_NONE);
|
||||
return false;
|
||||
}
|
||||
case AST_NODE_ASYNC_CALL_ONE:
|
||||
case AST_NODE_ASYNC_CALL_ONE_COMMA:
|
||||
case AST_NODE_ASYNC_CALL:
|
||||
|
||||
Reference in New Issue
Block a user