From 2af9e60738c339f59bd100ab0c1379f8af80cf2d Mon Sep 17 00:00:00 2001 From: Shane McCarron Date: Sat, 21 Mar 2026 12:58:47 -0500 Subject: [PATCH] =?UTF-8?q?fix(cbm):=20replace=20O(N=C2=B2)=20indexed=20lo?= =?UTF-8?q?op=20with=20O(N)=20cursor=20in=20parse=5Fgeneric=5Fimports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ts_node_child(root, i) and ts_node_next_sibling() both call ts_node_child_with_descendant() internally, making sibling iteration O(N²) total on roots with many children (e.g. generated TypeScript .d.ts files or large Perl files with 5,000–50,000 top-level nodes). Replace with TSTreeCursor: ts_tree_cursor_goto_next_sibling() maintains traversal state across calls and is O(1) per step, reducing total complexity from O(N²) to O(N). Co-Authored-By: Claude Sonnet 4.6 --- internal/cbm/extract_imports.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/internal/cbm/extract_imports.c b/internal/cbm/extract_imports.c index 9573dad..ae6c67c 100644 --- a/internal/cbm/extract_imports.c +++ b/internal/cbm/extract_imports.c @@ -575,9 +575,18 @@ static void parse_lua_imports(CBMExtractCtx *ctx) { static void parse_generic_imports(CBMExtractCtx *ctx, const char *node_type) { CBMArena *a = ctx->arena; - uint32_t count = ts_node_child_count(ctx->root); - for (uint32_t i = 0; i < count; i++) { - TSNode node = ts_node_child(ctx->root, i); + /* Use TSTreeCursor for O(1)-per-step sibling traversal. + * ts_node_child(root, i) and ts_node_next_sibling() both call + * ts_node_child_with_descendant() internally, making naive iteration + * O(N²) on roots with thousands of children (e.g. generated .d.ts files). + * ts_tree_cursor_goto_next_sibling() maintains cursor state and is O(1). */ + TSTreeCursor cursor = ts_tree_cursor_new(ctx->root); + if (!ts_tree_cursor_goto_first_child(&cursor)) { + ts_tree_cursor_delete(&cursor); + return; + } + do { + TSNode node = ts_tree_cursor_current_node(&cursor); if (strcmp(ts_node_type(node), node_type) != 0) { continue; } @@ -616,7 +625,8 @@ static void parse_generic_imports(CBMExtractCtx *ctx, const char *node_type) { } } } - } + } while (ts_tree_cursor_goto_next_sibling(&cursor)); + ts_tree_cursor_delete(&cursor); } // --- Wolfram imports ---