From 4d185780007289470d06488263305c4122712765 Mon Sep 17 00:00:00 2001 From: Lalit Maganti Date: Sun, 27 Sep 2026 16:54:53 +0100 Subject: [PATCH] tp: roll syntaqlite to 0.12.1 0.11.0 renamed macro rewrites to rewrites, since a dialect's host can now expand parsed nodes too: syntaqlite_result_macro_count and syntaqlite_result_macro_rewrite_at are syntaqlite_result_rewrite_count and syntaqlite_result_rewrite_at, SyntaqliteMacroRewrite is SyntaqliteRewrite, and SYNTAQLITE_MACRO_PARENT_SOURCE is SYNTAQLITE_REWRITE_PARENT_SOURCE. 0.12.0 expands such nodes once their statement is parsed, and generates the same keyword tables on every run. 0.12.1 lets the expander read the statement's root, even for the first statement of a source. Update the parser and the analysis source tree to the new names, bump the CLI and npm pins, and regenerate the vendored parser. --- src/perfetto_sql/analysis/source_tree.cc | 4 +- .../syntaqlite/syntaqlite_perfetto.c | 633 ++++++++++++++---- .../syntaqlite/syntaqlite_perfetto.h | 136 +++- .../parser/perfetto_sql_parser.cc | 20 +- tools/install-build-deps | 24 +- ui/package.json | 2 +- ui/pnpm-lock.yaml | 11 +- 7 files changed, 648 insertions(+), 182 deletions(-) diff --git a/src/perfetto_sql/analysis/source_tree.cc b/src/perfetto_sql/analysis/source_tree.cc index 10b88ee156e..20594017f09 100644 --- a/src/perfetto_sql/analysis/source_tree.cc +++ b/src/perfetto_sql/analysis/source_tree.cc @@ -275,9 +275,9 @@ void CollectStatementRefs(SyntaqliteParser* p, RawRefs& out) { break; } } - uint32_t rw_count = syntaqlite_result_macro_count(p); + uint32_t rw_count = syntaqlite_result_rewrite_count(p); for (uint32_t i = 0; i < rw_count; ++i) { - SyntaqliteMacroRewrite rw = syntaqlite_result_macro_rewrite_at(p, i); + SyntaqliteRewrite rw = syntaqlite_result_rewrite_at(p, i); if (rw.name && rw.name_len > 0) out.macro_invocations.Insert(std::string(rw.name, rw.name_len)); } diff --git a/src/perfetto_sql/syntaqlite/syntaqlite_perfetto.c b/src/perfetto_sql/syntaqlite/syntaqlite_perfetto.c index ee09257f237..dab71236e8f 100644 --- a/src/perfetto_sql/syntaqlite/syntaqlite_perfetto.c +++ b/src/perfetto_sql/syntaqlite/syntaqlite_perfetto.c @@ -375,6 +375,29 @@ typedef struct SynqNodeExpandedExtent { uint32_t layer_id; } SynqNodeExpandedExtent; +// The first and last tokens under a node, each with the layer it came from. +// This tells us where a node starts and ends even when it spans macro +// expansions, which is how we find the layer a node was written in (see +// `syntaqlite_parser_node_site`). +// +// A node with no tokens has first_layer == SYNQ_NO_BOUNDS, which is ignored +// when merging. +// A node the grammar marked for the host to expand (see +// `synq_parser_expand_node`). +typedef struct SynqMarkedNode { + uint32_t node_id; + const char* name; + uint32_t name_len; +} SynqMarkedNode; + +#define SYNQ_NO_BOUNDS UINT32_MAX +typedef struct SynqNodeBounds { + uint32_t first_layer; + uint32_t first_offset; + uint32_t last_layer; + uint32_t last_end; +} SynqNodeBounds; + // Straddle stack entry values (packed into uint32_t): // 0 = source terminal // 1..N = terminal from outermost expansion layer N @@ -455,6 +478,9 @@ typedef struct SynqParseCtx { SYNQ_VEC(SynqExtentRange) node_extents; SYNQ_VEC(SynqNodeExpandedExtent) expanded_stack; SYNQ_VEC(SynqNodeExpandedExtent) node_expanded_extents; + SYNQ_VEC(SynqNodeBounds) bounds_stack; + SYNQ_VEC(SynqNodeBounds) node_bounds; + SYNQ_VEC(SynqMarkedNode) marked_nodes; uint32_t collect_node_extents; uint32_t macro_root_start; uint32_t macro_root_end; @@ -467,6 +493,18 @@ typedef struct SynqParseCtx { uint32_t generated_always; } SynqParseCtx; +// Marks the node just built for the host's node expander (see +// `syntaqlite_parser_set_node_expander`) to replace once the statement is +// parsed. `name` becomes the rewrite's name, like a macro name, and shows up +// in tracebacks. +static inline void synq_parser_expand_node(SynqParseCtx* ctx, + uint32_t node_id, + const char* name, + uint32_t name_len) { + SynqMarkedNode node = {node_id, name, name_len}; + syntaqlite_vec_push(&ctx->marked_nodes, node, ctx->mem); +} + // Common header for all list nodes in the arena. typedef struct SynqListHeader { uint32_t tag; @@ -517,6 +555,9 @@ static inline void synq_parse_ctx_init(SynqParseCtx* ctx, syntaqlite_vec_init(&ctx->node_extents); syntaqlite_vec_init(&ctx->expanded_stack); syntaqlite_vec_init(&ctx->node_expanded_extents); + syntaqlite_vec_init(&ctx->bounds_stack); + syntaqlite_vec_init(&ctx->node_bounds); + syntaqlite_vec_init(&ctx->marked_nodes); ctx->collect_node_extents = 0; ctx->macro_root_start = 0; ctx->macro_root_end = 0; @@ -534,6 +575,9 @@ static inline void synq_parse_ctx_free(SynqParseCtx* ctx) { syntaqlite_vec_free(&ctx->node_extents, ctx->mem); syntaqlite_vec_free(&ctx->expanded_stack, ctx->mem); syntaqlite_vec_free(&ctx->node_expanded_extents, ctx->mem); + syntaqlite_vec_free(&ctx->bounds_stack, ctx->mem); + syntaqlite_vec_free(&ctx->node_bounds, ctx->mem); + syntaqlite_vec_free(&ctx->marked_nodes, ctx->mem); syntaqlite_vec_free(&ctx->straddle_stack, ctx->mem); synq_arena_free(&ctx->ast, ctx->mem); } @@ -546,6 +590,9 @@ static inline void synq_parse_ctx_clear(SynqParseCtx* ctx) { syntaqlite_vec_clear(&ctx->node_extents); syntaqlite_vec_clear(&ctx->expanded_stack); syntaqlite_vec_clear(&ctx->node_expanded_extents); + syntaqlite_vec_clear(&ctx->bounds_stack); + syntaqlite_vec_clear(&ctx->node_bounds); + syntaqlite_vec_clear(&ctx->marked_nodes); synq_arena_clear(&ctx->ast); ctx->macro_root_start = 0; ctx->macro_root_end = 0; @@ -573,12 +620,17 @@ static inline void synq_extent_record(SynqParseCtx* ctx, uint32_t node_id) { SynqExtentRange top = syntaqlite_vec_at(&ctx->extent_stack, stack_len - 1); SynqNodeExpandedExtent exp_top = syntaqlite_vec_at(&ctx->expanded_stack, stack_len - 1); + SynqNodeBounds* bounds_entry = + &syntaqlite_vec_at(&ctx->bounds_stack, stack_len - 1); + SynqNodeBounds bounds_top = *bounds_entry; if (node_id < ctx->node_extents.count) { syntaqlite_vec_at(&ctx->node_extents, node_id) = top; syntaqlite_vec_at(&ctx->node_expanded_extents, node_id) = exp_top; + syntaqlite_vec_at(&ctx->node_bounds, node_id) = bounds_top; } else { syntaqlite_vec_push(&ctx->node_extents, top, ctx->mem); syntaqlite_vec_push(&ctx->node_expanded_extents, exp_top, ctx->mem); + syntaqlite_vec_push(&ctx->node_bounds, bounds_top, ctx->mem); } } @@ -6273,13 +6325,33 @@ typedef struct SynqExpansionLayer { uint32_t body_call_length; uint32_t parent_layer_id; // Layer containing the call (0 = source). + + // A SyntaqliteRewriteKind. + uint32_t kind; } SynqExpansionLayer; typedef SYNQ_VEC(SynqExpansionLayer) SynqExpansionLayerVec; -// All macro-related parser state, including layer tree and scratch buffers. -// Factored into a single sub-struct so the parser struct has one guarded -// field: `SynqMacroState macro;`. +// Finds the layer a node was written in (the innermost one containing both its +// first and last tokens; 0 is the source) and the node's [start, end) within +// it. Returns 0 if extents aren't being collected or the node has no tokens. +int synq_node_site(SyntaqliteParser* p, + uint32_t node_id, + uint32_t* layer, + uint32_t* start, + uint32_t* end); + +// Maps a call in `parent`'s expansion back to its position in `parent`'s +// authored body. If the call came from a substituted $param argument, both +// outputs are set to SYNTAQLITE_MACRO_BODY_CALL_ARG_INTERNAL. +void synq_body_call_range(const SynqExpansionLayer* parent, + uint32_t call_offset, + uint32_t call_length, + uint32_t* body_offset, + uint32_t* body_length); + +// Macro expansion state: the lookup callback, the invocation in progress and +// its scratch. The layers macro calls add live in `SynqRewriteState`. typedef struct SynqMacroState { // ── Configuration ────────────────────────────────────────────────────── uint32_t macro_fallback; // 1 = unregistered name!(args) becomes TK_ID. @@ -6302,9 +6374,23 @@ typedef struct SynqMacroState { // ── Nesting depth (0 = not in macro) ─────────────────────────────────── uint32_t depth; +} SynqMacroState; + +// State for node expansion: the host's callback, and the text it gave the +// node it is expanding. +typedef struct SynqNodeExpansionState { + SyntaqliteNodeExpandFn expander; + void* user_data; + char* result; + uint32_t result_len; +} SynqNodeExpansionState; + +// The rewrites recorded for the current statement, each a layer of text +// replacing a range of its parent's: a macro call's expansion, for one. +typedef struct SynqRewriteState { // ── Layer tree ───────────────────────────────────────────────────────── // Entry 0 is a sentinel representing the original source; actual - // expansions start at index 1. `_layer_id` on AST spans indexes + // rewrites start at index 1. `_layer_id` on AST spans indexes // directly into this vector. SynqExpansionLayerVec layers; @@ -6313,7 +6399,7 @@ typedef struct SynqMacroState { SYNQ_VEC(SyntaqliteTracebackFrame) traceback_buf; // Scratch for `syntaqlite_parser_node_expanded_text`. SYNQ_VEC(uint8_t) node_expanded_buf; -} SynqMacroState; +} SynqRewriteState; #endif // !SYNTAQLITE_OMIT_MACROS @@ -6382,9 +6468,12 @@ struct SyntaqliteParser { // non-empty: trailing comments always have a previous token. SynqTokenComments pending_orphan_leading; - // ── Macro expansion state (compiled out with SYNTAQLITE_OMIT_MACROS) ─── + // ── Macro expansion and rewrite state (compiled out with + // SYNTAQLITE_OMIT_MACROS) ───────────────────────────────────────────── #ifndef SYNTAQLITE_OMIT_MACROS SynqMacroState macro; + SynqNodeExpansionState node_expansion; + SynqRewriteState rewrites; #endif }; @@ -6477,6 +6566,14 @@ void synq_macro_state_init(SynqMacroState* m); // Free all macro state buffers. void synq_macro_state_free(SynqMacroState* m, SyntaqliteMemMethods mem); +// Expands the nodes the statement just parsed marked, innermost first. +// Returns 0, with the parser's error set, if one of them fails. +int synq_parser_expand_nodes(SyntaqliteParser* p); + +// Initialize and free the rewrite layer tree and its scratch. +void synq_rewrite_state_init(SynqRewriteState* r); +void synq_rewrite_state_free(SynqRewriteState* r, SyntaqliteMemMethods mem); + // Free owned expansion data and arg segments on layers 1..N (skip sentinel). void synq_layers_free_owned(SynqExpansionLayerVec* layers, SyntaqliteMemMethods mem); @@ -6531,8 +6628,8 @@ static void synq_open_statement(SyntaqliteParser* p, uint32_t offset) { p->stmt_start_offset = offset; p->stmt_source = p->source + offset; #ifndef SYNTAQLITE_OMIT_MACROS - if (syntaqlite_vec_len(&p->macro.layers) > 0) { - SynqExpansionLayer* root = &p->macro.layers.data[0]; + if (syntaqlite_vec_len(&p->rewrites.layers) > 0) { + SynqExpansionLayer* root = &p->rewrites.layers.data[0]; root->expansion_data = p->stmt_source; root->expansion_len = p->source_len - offset; } @@ -6540,11 +6637,20 @@ static void synq_open_statement(SyntaqliteParser* p, uint32_t offset) { } int32_t synq_parser_set_result_status(SyntaqliteParser* p, int32_t rc) { - p->last_status = rc; if (p->stmt_start_offset != UINT32_MAX) { p->stmt_end_offset = p->offset > p->stmt_start_offset ? p->offset : p->stmt_start_offset; } + p->last_status = rc; +#ifndef SYNTAQLITE_OMIT_MACROS + // The statement is whole now, so the nodes it marked can be expanded. The + // status is set first so the expander can read the statement's result, such + // as its root. + if (rc == SYNTAQLITE_PARSE_OK && !synq_parser_expand_nodes(p)) { + rc = SYNTAQLITE_PARSE_ERROR; + p->last_status = rc; + } +#endif return rc; } @@ -6579,12 +6685,12 @@ static void reset_stmt(SyntaqliteParser* p) { syntaqlite_vec_clear(&p->token_comments); p->pending_orphan_leading = SYNQ_TOKEN_COMMENTS_EMPTY; #ifndef SYNTAQLITE_OMIT_MACROS - syntaqlite_vec_clear(&p->macro.traceback_buf); - syntaqlite_vec_clear(&p->macro.node_expanded_buf); - synq_layers_free_owned(&p->macro.layers, p->mem); - syntaqlite_vec_clear(&p->macro.layers); + syntaqlite_vec_clear(&p->rewrites.traceback_buf); + syntaqlite_vec_clear(&p->rewrites.node_expanded_buf); + synq_layers_free_owned(&p->rewrites.layers, p->mem); + syntaqlite_vec_clear(&p->rewrites.layers); if (p->source) - synq_layers_push_sentinel(&p->macro.layers, p->source, p->source_len, + synq_layers_push_sentinel(&p->rewrites.layers, p->source, p->source_len, p->mem); #endif p->ctx.layer_id = 0; @@ -6649,6 +6755,7 @@ SYNTAQLITE_API SyntaqliteParser* syntaqlite_parser_create_with_dialect( p->pending_orphan_leading = SYNQ_TOKEN_COMMENTS_EMPTY; #ifndef SYNTAQLITE_OMIT_MACROS synq_macro_state_init(&p->macro); + synq_rewrite_state_init(&p->rewrites); #endif return p; } @@ -6681,8 +6788,8 @@ SYNTAQLITE_API void syntaqlite_parser_reset(SyntaqliteParser* p, p->stmt_source = source; #ifndef SYNTAQLITE_OMIT_MACROS p->macro.depth = 0; - syntaqlite_vec_clear(&p->macro.layers); - synq_layers_push_sentinel(&p->macro.layers, source, len, p->mem); + syntaqlite_vec_clear(&p->rewrites.layers); + synq_layers_push_sentinel(&p->rewrites.layers, source, len, p->mem); #endif p->ctx.source = source; @@ -6698,6 +6805,7 @@ SYNTAQLITE_API void syntaqlite_parser_destroy(SyntaqliteParser* p) { syntaqlite_vec_free(&p->tokens, p->mem); #ifndef SYNTAQLITE_OMIT_MACROS synq_macro_state_free(&p->macro, p->mem); + synq_rewrite_state_free(&p->rewrites, p->mem); #endif p->mem.xFree(p); } @@ -6943,14 +7051,15 @@ void synq_parser_record_comment(SyntaqliteParser* p, #ifndef SYNTAQLITE_OMIT_MACROS else if (layer == 0 && p->last_pushed_token_layer != UINT32_MAX && p->last_pushed_token_layer > 0 && - p->last_pushed_token_layer < syntaqlite_vec_len(&p->macro.layers)) { + p->last_pushed_token_layer < + syntaqlite_vec_len(&p->rewrites.layers)) { // Prev token was inside an expansion; comment is in source. Compare // against the end of the topmost ancestor macro call in source. uint32_t L = p->last_pushed_token_layer; - while (L > 0 && p->macro.layers.data[L].parent_layer_id != 0) - L = p->macro.layers.data[L].parent_layer_id; + while (L > 0 && p->rewrites.layers.data[L].parent_layer_id != 0) + L = p->rewrites.layers.data[L].parent_layer_id; if (L > 0) { - const SynqExpansionLayer* lyr = &p->macro.layers.data[L]; + const SynqExpansionLayer* lyr = &p->rewrites.layers.data[L]; uint32_t call_end = p->stmt_start_offset + lyr->call_offset + lyr->call_length; if (call_end <= offset) @@ -6968,11 +7077,12 @@ void synq_parser_record_comment(SyntaqliteParser* p, if (!is_block) { is_trailing = 1; } else { - uint32_t buf_len = layer == 0 ? p->source_len + uint32_t buf_len = layer == 0 + ? p->source_len #ifndef SYNTAQLITE_OMIT_MACROS - : p->macro.layers.data[layer].expansion_len + : p->rewrites.layers.data[layer].expansion_len #else - : 0 + : 0 #endif ; uint32_t next = @@ -7382,16 +7492,32 @@ SYNTAQLITE_API const SyntaqliteComment* syntaqlite_node_trailing_comments( } #ifdef SYNTAQLITE_OMIT_MACROS -SYNTAQLITE_API uint32_t syntaqlite_result_macro_count(SyntaqliteParser* p) { +SYNTAQLITE_API uint32_t syntaqlite_result_rewrite_count(SyntaqliteParser* p) { (void)p; return 0; } -SYNTAQLITE_API SyntaqliteMacroRewrite -syntaqlite_result_macro_rewrite_at(SyntaqliteParser* p, uint32_t idx) { +SYNTAQLITE_API int32_t +syntaqlite_parser_set_node_expander(SyntaqliteParser* p, + SyntaqliteNodeExpandFn fn, + void* user_data) { + (void)p; + (void)fn; + (void)user_data; + return SYNTAQLITE_ERR_OMITTED; +} +SYNTAQLITE_API void syntaqlite_node_expansion_set_result(SyntaqliteParser* p, + const char* text, + uint32_t len) { + (void)p; + (void)text; + (void)len; +} +SYNTAQLITE_API SyntaqliteRewrite +syntaqlite_result_rewrite_at(SyntaqliteParser* p, uint32_t idx) { (void)p; (void)idx; - return (SyntaqliteMacroRewrite){ - .parent_idx = SYNTAQLITE_MACRO_PARENT_SOURCE, + return (SyntaqliteRewrite){ + .parent_idx = SYNTAQLITE_REWRITE_PARENT_SOURCE, }; } SYNTAQLITE_API uint32_t @@ -7426,26 +7552,26 @@ syntaqlite_macro_rewrite_arg_at(SyntaqliteParser* p, return (SyntaqliteMacroCallArg){0}; } #else -SYNTAQLITE_API uint32_t syntaqlite_result_macro_count(SyntaqliteParser* p) { - uint32_t total = syntaqlite_vec_len(&p->macro.layers); +SYNTAQLITE_API uint32_t syntaqlite_result_rewrite_count(SyntaqliteParser* p) { + uint32_t total = syntaqlite_vec_len(&p->rewrites.layers); // Entry 0 is the source sentinel; real expansion layers start at 1. return total <= 1 ? 0 : total - 1; } -SYNTAQLITE_API SyntaqliteMacroRewrite -syntaqlite_result_macro_rewrite_at(SyntaqliteParser* p, uint32_t idx) { +SYNTAQLITE_API SyntaqliteRewrite +syntaqlite_result_rewrite_at(SyntaqliteParser* p, uint32_t idx) { // +1 to skip the source sentinel at index 0. uint32_t layer_idx = idx + 1; - if (layer_idx >= syntaqlite_vec_len(&p->macro.layers)) { - return (SyntaqliteMacroRewrite){ - .parent_idx = SYNTAQLITE_MACRO_PARENT_SOURCE, + if (layer_idx >= syntaqlite_vec_len(&p->rewrites.layers)) { + return (SyntaqliteRewrite){ + .parent_idx = SYNTAQLITE_REWRITE_PARENT_SOURCE, }; } - const SynqExpansionLayer* lyr = &p->macro.layers.data[layer_idx]; + const SynqExpansionLayer* lyr = &p->rewrites.layers.data[layer_idx]; // Internal parent_layer_id 0 = authored source sentinel. Map it to the // public sentinel value; otherwise subtract 1 to account for the skipped // source entry. uint32_t parent_idx = lyr->parent_layer_id == 0 - ? SYNTAQLITE_MACRO_PARENT_SOURCE + ? SYNTAQLITE_REWRITE_PARENT_SOURCE : lyr->parent_layer_id - 1; // Resolve the buffer that `call_offset` and every arg offset // measure into, so consumers can slice directly without walking @@ -7459,11 +7585,11 @@ syntaqlite_result_macro_rewrite_at(SyntaqliteParser* p, uint32_t idx) { parent_buffer_len = p->stmt_end_offset - p->stmt_start_offset; } else { const SynqExpansionLayer* parent = - &p->macro.layers.data[lyr->parent_layer_id]; + &p->rewrites.layers.data[lyr->parent_layer_id]; parent_buffer = parent->expansion_data; parent_buffer_len = parent->expansion_len; } - return (SyntaqliteMacroRewrite){ + return (SyntaqliteRewrite){ .parent_idx = parent_idx, .call_offset = lyr->call_offset, .call_length = lyr->call_length, @@ -7478,6 +7604,7 @@ syntaqlite_result_macro_rewrite_at(SyntaqliteParser* p, uint32_t idx) { .parent_buffer = parent_buffer, .parent_buffer_len = parent_buffer_len, .is_fallback = lyr->is_fallback, + .kind = lyr->kind, }; } @@ -7485,9 +7612,9 @@ SYNTAQLITE_API uint32_t syntaqlite_macro_rewrite_arg_segment_count(SyntaqliteParser* p, uint32_t rewrite_idx) { uint32_t layer_idx = rewrite_idx + 1; - if (layer_idx >= syntaqlite_vec_len(&p->macro.layers)) + if (layer_idx >= syntaqlite_vec_len(&p->rewrites.layers)) return 0; - return p->macro.layers.data[layer_idx].arg_segment_count; + return p->rewrites.layers.data[layer_idx].arg_segment_count; } SYNTAQLITE_API SyntaqliteMacroArgSegment @@ -7495,16 +7622,16 @@ syntaqlite_macro_rewrite_arg_segment_at(SyntaqliteParser* p, uint32_t rewrite_idx, uint32_t segment_idx) { uint32_t layer_idx = rewrite_idx + 1; - if (layer_idx >= syntaqlite_vec_len(&p->macro.layers)) + if (layer_idx >= syntaqlite_vec_len(&p->rewrites.layers)) return (SyntaqliteMacroArgSegment){0}; - const SynqExpansionLayer* lyr = &p->macro.layers.data[layer_idx]; + const SynqExpansionLayer* lyr = &p->rewrites.layers.data[layer_idx]; if (segment_idx >= lyr->arg_segment_count) return (SyntaqliteMacroArgSegment){0}; const SynqArgSegment* seg = &lyr->arg_segments[segment_idx]; // Map internal origin_layer_id (0 = source sentinel) to the public // sentinel / rewrite-index scheme used by parent_idx. uint32_t origin_parent_idx = seg->origin_layer_id == 0 - ? SYNTAQLITE_MACRO_PARENT_SOURCE + ? SYNTAQLITE_REWRITE_PARENT_SOURCE : seg->origin_layer_id - 1; return (SyntaqliteMacroArgSegment){ .body_offset = seg->body_offset, @@ -7520,9 +7647,9 @@ syntaqlite_macro_rewrite_arg_segment_at(SyntaqliteParser* p, SYNTAQLITE_API uint32_t syntaqlite_macro_rewrite_arg_count(SyntaqliteParser* p, uint32_t rewrite_idx) { uint32_t layer_idx = rewrite_idx + 1; - if (layer_idx >= syntaqlite_vec_len(&p->macro.layers)) + if (layer_idx >= syntaqlite_vec_len(&p->rewrites.layers)) return 0; - return p->macro.layers.data[layer_idx].arg_count; + return p->rewrites.layers.data[layer_idx].arg_count; } SYNTAQLITE_API SyntaqliteMacroCallArg @@ -7530,9 +7657,9 @@ syntaqlite_macro_rewrite_arg_at(SyntaqliteParser* p, uint32_t rewrite_idx, uint32_t arg_idx) { uint32_t layer_idx = rewrite_idx + 1; - if (layer_idx >= syntaqlite_vec_len(&p->macro.layers)) + if (layer_idx >= syntaqlite_vec_len(&p->rewrites.layers)) return (SyntaqliteMacroCallArg){0}; - const SynqExpansionLayer* lyr = &p->macro.layers.data[layer_idx]; + const SynqExpansionLayer* lyr = &p->rewrites.layers.data[layer_idx]; if (arg_idx >= lyr->arg_count) return (SyntaqliteMacroCallArg){0}; const SynqMacroArg* arg = &lyr->args[arg_idx]; @@ -7616,10 +7743,10 @@ SYNTAQLITE_API const char* syntaqlite_parser_layer_text( (void)layer_id; return NULL; #else - if (layer_id >= syntaqlite_vec_len(&p->macro.layers)) { + if (layer_id >= syntaqlite_vec_len(&p->rewrites.layers)) { return NULL; } - const SynqExpansionLayer* lyr = &p->macro.layers.data[layer_id]; + const SynqExpansionLayer* lyr = &p->rewrites.layers.data[layer_id]; if (out_len) { *out_len = lyr->expansion_len; } @@ -7643,12 +7770,12 @@ SYNTAQLITE_API const char* syntaqlite_parser_expanded_text(SyntaqliteParser* p, return ""; } uint32_t stmt_len = p->stmt_end_offset - p->stmt_start_offset; - syntaqlite_vec_clear(&p->macro.node_expanded_buf); + syntaqlite_vec_clear(&p->rewrites.node_expanded_buf); append_expanded_range(p, 0, p->stmt_source, stmt_len, 0, stmt_len); if (out_len) { - *out_len = syntaqlite_vec_len(&p->macro.node_expanded_buf); + *out_len = syntaqlite_vec_len(&p->rewrites.node_expanded_buf); } - return (const char*)p->macro.node_expanded_buf.data; + return (const char*)p->rewrites.node_expanded_buf.data; #endif } @@ -7843,31 +7970,37 @@ static void append_expanded_range(SyntaqliteParser* p, if (end > buf_len) end = buf_len; uint32_t cursor = start; - uint32_t nlayers = syntaqlite_vec_len(&p->macro.layers); + uint32_t nlayers = syntaqlite_vec_len(&p->rewrites.layers); for (;;) { // Find the next child layer (parent == layer_id) whose call site // begins at or after `cursor` and lies fully within `[start, end)`. uint32_t best_child = 0; uint32_t best_offset = UINT32_MAX; for (uint32_t i = 1; i < nlayers; i++) { - const SynqExpansionLayer* lyr = &p->macro.layers.data[i]; + const SynqExpansionLayer* lyr = &p->rewrites.layers.data[i]; if (lyr->parent_layer_id != layer_id) continue; if (lyr->call_offset < cursor) continue; if (lyr->call_offset + lyr->call_length > end) continue; - if (lyr->call_offset < best_offset) { + // A node expansion and a macro call inside it can start at the same + // offset. Prefer the longer one: it's the outer one and replaces the + // other. + if (lyr->call_offset < best_offset || + (lyr->call_offset == best_offset && + lyr->call_length > + p->rewrites.layers.data[best_child].call_length)) { best_offset = lyr->call_offset; best_child = i; } } if (best_child == 0) break; - const SynqExpansionLayer* child = &p->macro.layers.data[best_child]; + const SynqExpansionLayer* child = &p->rewrites.layers.data[best_child]; if (best_offset > cursor) { uint32_t n = best_offset - cursor; - syntaqlite_vec_push_n(&p->macro.node_expanded_buf, buf + cursor, n, + syntaqlite_vec_push_n(&p->rewrites.node_expanded_buf, buf + cursor, n, p->mem); } append_expanded_range(p, best_child, child->expansion_data, @@ -7876,7 +8009,8 @@ static void append_expanded_range(SyntaqliteParser* p, } if (end > cursor) { uint32_t n = end - cursor; - syntaqlite_vec_push_n(&p->macro.node_expanded_buf, buf + cursor, n, p->mem); + syntaqlite_vec_push_n(&p->rewrites.node_expanded_buf, buf + cursor, n, + p->mem); } } #endif // !SYNTAQLITE_OMIT_MACROS @@ -7904,7 +8038,7 @@ SYNTAQLITE_API const char* syntaqlite_parser_node_expanded_text( if (e.length > 0) { const char* buf = e.layer_id == 0 ? p->stmt_source - : p->macro.layers.data[e.layer_id].expansion_data; + : p->rewrites.layers.data[e.layer_id].expansion_data; if (out_len) { *out_len = e.length; } @@ -7921,13 +8055,102 @@ SYNTAQLITE_API const char* syntaqlite_parser_node_expanded_text( if (r.root_start > r.root_end || r.root_end > stmt_len) { return NULL; } - syntaqlite_vec_clear(&p->macro.node_expanded_buf); + syntaqlite_vec_clear(&p->rewrites.node_expanded_buf); append_expanded_range(p, 0, p->stmt_source, stmt_len, r.root_start, r.root_end); if (out_len) { - *out_len = syntaqlite_vec_len(&p->macro.node_expanded_buf); + *out_len = syntaqlite_vec_len(&p->rewrites.node_expanded_buf); + } + return (const char*)p->rewrites.node_expanded_buf.data; +#endif +} + +// --------------------------------------------------------------------------- +// Node sites and node rewrites +// --------------------------------------------------------------------------- + +#ifndef SYNTAQLITE_OMIT_MACROS +// Returns whether `layer` is `ancestor` or is nested somewhere inside it. +static int synq_layer_within(SyntaqliteParser* p, + uint32_t layer, + uint32_t ancestor) { + for (;;) { + if (layer == ancestor) + return 1; + if (layer == 0) + return 0; + layer = p->rewrites.layers.data[layer].parent_layer_id; + } +} + +// Returns the child of `ancestor` that `layer` is nested under. +static uint32_t synq_layer_child_of(SyntaqliteParser* p, + uint32_t layer, + uint32_t ancestor) { + while (p->rewrites.layers.data[layer].parent_layer_id != ancestor) + layer = p->rewrites.layers.data[layer].parent_layer_id; + return layer; +} + +// Like syntaqlite_parser_node_site, but returns the internal layer id (0 is the +// source). +int synq_node_site(SyntaqliteParser* p, + uint32_t node_id, + uint32_t* layer, + uint32_t* start, + uint32_t* end) { + if (!p->ctx.collect_node_extents || + node_id >= syntaqlite_vec_len(&p->ctx.node_bounds)) { + return 0; + } + SynqNodeBounds b = syntaqlite_vec_at(&p->ctx.node_bounds, node_id); + if (b.first_layer == SYNQ_NO_BOUNDS) + return 0; + // Find the innermost layer containing both the first and last token. + uint32_t home = b.first_layer; + while (!synq_layer_within(p, b.last_layer, home)) + home = p->rewrites.layers.data[home].parent_layer_id; + if (b.first_layer == home) { + *start = b.first_offset; + } else { + *start = + p->rewrites.layers.data[synq_layer_child_of(p, b.first_layer, home)] + .call_offset; + } + if (b.last_layer == home) { + *end = b.last_end; + } else { + const SynqExpansionLayer* call = + &p->rewrites.layers.data[synq_layer_child_of(p, b.last_layer, home)]; + *end = call->call_offset + call->call_length; } - return (const char*)p->macro.node_expanded_buf.data; + *layer = home; + return 1; +} +#endif + +SYNTAQLITE_API int syntaqlite_parser_node_site(SyntaqliteParser* p, + uint32_t node_id, + SyntaqliteNodeSite* out) { +#ifdef SYNTAQLITE_OMIT_MACROS + uint32_t len = 0; + uint32_t offset = 0; + if (!syntaqlite_parser_node_text(p, node_id, &len, &offset)) + return 0; + *out = (SyntaqliteNodeSite){SYNTAQLITE_REWRITE_PARENT_SOURCE, offset, len}; + return 1; +#else + uint32_t layer = 0; + uint32_t start = 0; + uint32_t end = 0; + if (!synq_node_site(p, node_id, &layer, &start, &end)) + return 0; + *out = (SyntaqliteNodeSite){ + .parent_idx = layer == 0 ? SYNTAQLITE_REWRITE_PARENT_SOURCE : layer - 1, + .offset = start, + .length = end - start, + }; + return 1; #endif } @@ -8137,7 +8360,7 @@ static void dump_node_recursive(DumpBuf* b, #else sp._layer_id == 0 ? p->stmt_source - : p->macro.layers.data[sp._layer_id].expansion_data; + : p->rewrites.layers.data[sp._layer_id].expansion_data; #endif const char* text = base + sp.offset; char q = syntaqlite_span_quote_char(sp); @@ -8366,6 +8589,20 @@ static void synq_expanded_merge(SynqNodeExpandedExtent* acc, acc->length = end - start; } +// Children are merged left to right: the first child with tokens sets the start +// and the last one sets the end. +static void synq_bounds_merge(SynqNodeBounds* acc, SynqNodeBounds e) { + if (e.first_layer == SYNQ_NO_BOUNDS) { + return; + } + if (acc->first_layer == SYNQ_NO_BOUNDS) { + acc->first_layer = e.first_layer; + acc->first_offset = e.first_offset; + } + acc->last_layer = e.last_layer; + acc->last_end = e.last_end; +} + void synq_extent_record_list_append(SynqParseCtx* ctx, uint32_t list_id, uint32_t child) { @@ -8374,13 +8611,16 @@ void synq_extent_record_list_append(SynqParseCtx* ctx, SynqExtentRange range = syntaqlite_vec_at(&ctx->node_extents, child); SynqNodeExpandedExtent expanded = syntaqlite_vec_at(&ctx->node_expanded_extents, child); + SynqNodeBounds bounds = syntaqlite_vec_at(&ctx->node_bounds, child); if (list_id < syntaqlite_vec_len(&ctx->node_extents)) { synq_extent_merge(&syntaqlite_vec_at(&ctx->node_extents, list_id), range); synq_expanded_merge( &syntaqlite_vec_at(&ctx->node_expanded_extents, list_id), expanded); + synq_bounds_merge(&syntaqlite_vec_at(&ctx->node_bounds, list_id), bounds); } else { syntaqlite_vec_push(&ctx->node_extents, range, ctx->mem); syntaqlite_vec_push(&ctx->node_expanded_extents, expanded, ctx->mem); + syntaqlite_vec_push(&ctx->node_bounds, bounds, ctx->mem); } } @@ -8427,6 +8667,13 @@ void synq_extent_on_shift(SynqParseCtx* pCtx, .layer_id = token->layer_id, }; syntaqlite_vec_push(&pCtx->expanded_stack, e, pCtx->mem); + SynqNodeBounds b = { + .first_layer = token->layer_id, + .first_offset = token->offset, + .last_layer = token->layer_id, + .last_end = token->offset + token->n, + }; + syntaqlite_vec_push(&pCtx->bounds_stack, b, pCtx->mem); } void synq_extent_on_reduce(SynqParseCtx* pCtx, unsigned int nrhs) { @@ -8480,6 +8727,14 @@ void synq_extent_on_reduce(SynqParseCtx* pCtx, unsigned int nrhs) { } syntaqlite_vec_truncate(&pCtx->expanded_stack, len - nrhs); syntaqlite_vec_push(&pCtx->expanded_stack, exp_merged, pCtx->mem); + + SynqNodeBounds bounds_merged = {SYNQ_NO_BOUNDS, 0, SYNQ_NO_BOUNDS, 0}; + for (uint32_t i = len - nrhs; i < len; i++) { + synq_bounds_merge(&bounds_merged, + syntaqlite_vec_at(&pCtx->bounds_stack, i)); + } + syntaqlite_vec_truncate(&pCtx->bounds_stack, len - nrhs); + syntaqlite_vec_push(&pCtx->bounds_stack, bounds_merged, pCtx->mem); } void synq_extent_fold_below_into_top(SynqParseCtx* pCtx) { @@ -8494,6 +8749,11 @@ void synq_extent_fold_below_into_top(SynqParseCtx* pCtx) { syntaqlite_vec_at(&pCtx->extent_stack, len - 2)); synq_expanded_merge(&syntaqlite_vec_at(&pCtx->expanded_stack, len - 1), syntaqlite_vec_at(&pCtx->expanded_stack, len - 2)); + // Bounds merge left to right, and the entry below comes first. + SynqNodeBounds* top = &syntaqlite_vec_at(&pCtx->bounds_stack, len - 1); + SynqNodeBounds merged = syntaqlite_vec_at(&pCtx->bounds_stack, len - 2); + synq_bounds_merge(&merged, *top); + *top = merged; } #endif /* !SYNTAQLITE_OMIT_RUNTIME */ /* ======== end: csrc/parser_extents.c ======== */ @@ -8707,18 +8967,24 @@ uint32_t synq_parser_scan_macro_args(SyntaqliteParser* p, void synq_macro_state_init(SynqMacroState* m) { syntaqlite_vec_init(&m->expand_buf); syntaqlite_vec_init(&m->body_buf); - syntaqlite_vec_init(&m->layers); - syntaqlite_vec_init(&m->traceback_buf); - syntaqlite_vec_init(&m->node_expanded_buf); } void synq_macro_state_free(SynqMacroState* m, SyntaqliteMemMethods mem) { syntaqlite_vec_free(&m->expand_buf, mem); syntaqlite_vec_free(&m->body_buf, mem); - synq_layers_free_owned(&m->layers, mem); - syntaqlite_vec_free(&m->layers, mem); - syntaqlite_vec_free(&m->traceback_buf, mem); - syntaqlite_vec_free(&m->node_expanded_buf, mem); +} + +void synq_rewrite_state_init(SynqRewriteState* r) { + syntaqlite_vec_init(&r->layers); + syntaqlite_vec_init(&r->traceback_buf); + syntaqlite_vec_init(&r->node_expanded_buf); +} + +void synq_rewrite_state_free(SynqRewriteState* r, SyntaqliteMemMethods mem) { + synq_layers_free_owned(&r->layers, mem); + syntaqlite_vec_free(&r->layers, mem); + syntaqlite_vec_free(&r->traceback_buf, mem); + syntaqlite_vec_free(&r->node_expanded_buf, mem); } void synq_layers_free_owned(SynqExpansionLayerVec* layers, @@ -8774,7 +9040,7 @@ SYNTAQLITE_API void syntaqlite_macro_expansion_set_result(SyntaqliteParser* p, uint32_t body_len, uint32_t def_line, uint32_t def_col) { - SynqExpansionLayer* lyr = &p->macro.layers.data[p->macro.pending_layer]; + SynqExpansionLayer* lyr = &p->rewrites.layers.data[p->macro.pending_layer]; layer_free_data(p, lyr); char* d = p->mem.xMalloc(body_len + 1); memcpy(d, body, body_len); @@ -8799,7 +9065,7 @@ SYNTAQLITE_API void syntaqlite_macro_expansion_set_result_with_arg_map( return; // Build resolved SynqArgSegment array from the caller's mappings. - SynqExpansionLayer* lyr = &p->macro.layers.data[p->macro.pending_layer]; + SynqExpansionLayer* lyr = &p->rewrites.layers.data[p->macro.pending_layer]; const SyntaqliteToken* args = p->macro.expansion_args; uint32_t arg_count = p->macro.expansion_arg_count; uint32_t origin_layer_id = lyr->parent_layer_id; @@ -8808,7 +9074,7 @@ SYNTAQLITE_API void syntaqlite_macro_expansion_set_result_with_arg_map( const char* origin_base = origin_layer_id == 0 ? p->stmt_source - : p->macro.layers.data[origin_layer_id].expansion_data; + : p->rewrites.layers.data[origin_layer_id].expansion_data; SynqArgSegment* segs = p->mem.xMalloc(mapping_count * sizeof(SynqArgSegment)); uint32_t seg_count = 0; @@ -8962,7 +9228,7 @@ int synq_parser_expand_and_feed_macro(SyntaqliteParser* p, { uint32_t walk = p->ctx.layer_id; if (walk > 0) { - const SynqExpansionLayer* cur = &p->macro.layers.data[walk]; + const SynqExpansionLayer* cur = &p->rewrites.layers.data[walk]; for (uint32_t i = 0; i < cur->arg_segment_count; i++) { const SynqArgSegment* seg = &cur->arg_segments[i]; if (id_offset >= seg->sub_offset && @@ -8973,7 +9239,7 @@ int synq_parser_expand_and_feed_macro(SyntaqliteParser* p, } } while (walk > 0) { - const SynqExpansionLayer* lyr = &p->macro.layers.data[walk]; + const SynqExpansionLayer* lyr = &p->rewrites.layers.data[walk]; if (synq_name_eq_ci(lyr->name, lyr->name_len, buf + id_offset, id_len)) { snprintf(p->error_msg, sizeof(p->error_msg), "recursive macro expansion: '%.*s'", (int)id_len, @@ -9005,7 +9271,7 @@ int synq_parser_expand_and_feed_macro(SyntaqliteParser* p, uint32_t call_length = end_offset - id_offset; begin_macro_expansion(p, id_offset, call_length, buf + id_offset, id_len); - uint32_t new_layer_idx = syntaqlite_vec_len(&p->macro.layers) - 1; + uint32_t new_layer_idx = syntaqlite_vec_len(&p->rewrites.layers) - 1; p->macro.pending_layer = new_layer_idx; p->macro.expansion_args = token_args; @@ -9017,14 +9283,14 @@ int synq_parser_expand_and_feed_macro(SyntaqliteParser* p, p->macro.expansion_arg_count = 0; if (rc == -1 || rc == -2) { - SynqExpansionLayer* lyr = &p->macro.layers.data[new_layer_idx]; + SynqExpansionLayer* lyr = &p->rewrites.layers.data[new_layer_idx]; if (lyr->expansion_data) p->mem.xFree((void*)lyr->expansion_data); if (lyr->arg_segments) p->mem.xFree(lyr->arg_segments); if (lyr->args) p->mem.xFree(lyr->args); - p->macro.layers.count--; + p->rewrites.layers.count--; p->macro.depth--; if (rc == -2) p->had_error = 1; @@ -9039,7 +9305,7 @@ int synq_parser_expand_and_feed_macro(SyntaqliteParser* p, // Offsets in `args[]` are buf-relative; rebase top-level layers to // statement-relative so they match how `begin_macro_expansion` // stored `call_offset`. - SynqExpansionLayer* lyr = &p->macro.layers.data[new_layer_idx]; + SynqExpansionLayer* lyr = &p->rewrites.layers.data[new_layer_idx]; if (token_arg_count > 0) { SynqMacroArg* heap = p->mem.xMalloc(token_arg_count * sizeof(SynqMacroArg)); uint32_t shift = lyr->parent_layer_id == 0 ? p->stmt_start_offset : 0; @@ -9074,6 +9340,42 @@ int synq_parser_expand_and_feed_macro(SyntaqliteParser* p, // Internal: push a new expansion layer. // expansion_data, def_line, def_col are left zeroed — the callback fills // them via set_result / expand_and_set_result. +// Maps the call at [call_offset, call_offset + call_length) in `parent`'s +// expansion back to `parent`'s authored body, by undoing the length changes +// from $param substitution. +void synq_body_call_range(const SynqExpansionLayer* parent, + uint32_t call_offset, + uint32_t call_length, + uint32_t* body_offset, + uint32_t* body_length) { + uint32_t call_end = call_offset + call_length; + int64_t prefix_shift = 0; + int64_t inner_shift = 0; + int arg_internal = 0; + for (uint32_t i = 0; i < parent->arg_segment_count; i++) { + const SynqArgSegment* seg = &parent->arg_segments[i]; + uint32_t seg_end = seg->sub_offset + seg->sub_length; + int64_t body_shift = (int64_t)seg->sub_length - (int64_t)seg->body_length; + if (seg_end <= call_offset) { + prefix_shift += body_shift; + } else if (seg->sub_offset >= call_end) { + // Fully after the call — no effect. + } else if (seg->sub_offset <= call_offset && seg_end >= call_end) { + arg_internal = 1; + break; + } else if (seg->sub_offset >= call_offset && seg_end <= call_end) { + inner_shift += body_shift; + } else { + arg_internal = 1; + break; + } + } + *body_offset = arg_internal ? SYNTAQLITE_MACRO_BODY_CALL_ARG_INTERNAL + : (uint32_t)((int64_t)call_offset - prefix_shift); + *body_length = arg_internal ? SYNTAQLITE_MACRO_BODY_CALL_ARG_INTERNAL + : (uint32_t)((int64_t)call_length - inner_shift); +} + static void begin_macro_expansion(SyntaqliteParser* p, uint32_t call_offset, uint32_t call_length, @@ -9097,7 +9399,7 @@ static void begin_macro_expansion(SyntaqliteParser* p, syntaqlite_vec_push(&p->ctx.straddle_stack, SYNQ_STRADDLE_NEUTRAL, p->mem); } - p->ctx.macro_root_layer = syntaqlite_vec_len(&p->macro.layers); + p->ctx.macro_root_layer = syntaqlite_vec_len(&p->rewrites.layers); } // Compute position of this call in the parent's *authored* body by @@ -9121,35 +9423,10 @@ static void begin_macro_expansion(SyntaqliteParser* p, // The "contains" check must run before "strictly inside" so the // equal-bounds case (common for `m!(arg)` where arg is itself a // macro call) is classified as arg-internal rather than inside. - const SynqExpansionLayer* parent = &p->macro.layers.data[p->ctx.layer_id]; - uint32_t call_end = call_offset + call_length; - int64_t prefix_shift = 0; - int64_t inner_shift = 0; - int arg_internal = 0; - for (uint32_t i = 0; i < parent->arg_segment_count; i++) { - const SynqArgSegment* seg = &parent->arg_segments[i]; - uint32_t seg_end = seg->sub_offset + seg->sub_length; - int64_t body_shift = (int64_t)seg->sub_length - (int64_t)seg->body_length; - if (seg_end <= call_offset) { - prefix_shift += body_shift; - } else if (seg->sub_offset >= call_end) { - // Fully after the call — no effect. - } else if (seg->sub_offset <= call_offset && seg_end >= call_end) { - arg_internal = 1; - break; - } else if (seg->sub_offset >= call_offset && seg_end <= call_end) { - inner_shift += body_shift; - } else { - arg_internal = 1; - break; - } - } - uint32_t body_call_offset = - arg_internal ? SYNTAQLITE_MACRO_BODY_CALL_ARG_INTERNAL - : (uint32_t)((int64_t)call_offset - prefix_shift); - uint32_t body_call_length = - arg_internal ? SYNTAQLITE_MACRO_BODY_CALL_ARG_INTERNAL - : (uint32_t)((int64_t)call_length - inner_shift); + uint32_t body_call_offset = 0; + uint32_t body_call_length = 0; + synq_body_call_range(&p->rewrites.layers.data[p->ctx.layer_id], call_offset, + call_length, &body_call_offset, &body_call_length); SynqExpansionLayer layer = { .call_offset = call_offset, @@ -9160,7 +9437,7 @@ static void begin_macro_expansion(SyntaqliteParser* p, .body_call_length = body_call_length, .parent_layer_id = p->ctx.layer_id, }; - syntaqlite_vec_push(&p->macro.layers, layer, p->mem); + syntaqlite_vec_push(&p->rewrites.layers, layer, p->mem); p->macro.depth++; } @@ -9174,8 +9451,8 @@ static void synq_end_macro(SyntaqliteParser* p) { } else { // Walk back to find the still-active parent layer. uint32_t cur = p->ctx.layer_id; - if (cur > 0 && cur < syntaqlite_vec_len(&p->macro.layers)) { - p->ctx.layer_id = p->macro.layers.data[cur].parent_layer_id; + if (cur > 0 && cur < syntaqlite_vec_len(&p->rewrites.layers)) { + p->ctx.layer_id = p->rewrites.layers.data[cur].parent_layer_id; } } } @@ -9252,13 +9529,13 @@ int synq_parser_try_macro_call(SyntaqliteParser* p, // read it from the rewrite directly without reparsing the call text. begin_macro_expansion(p, id_offset, call_length, (const char*)z + id_offset, id_len); - p->ctx.layer_id = syntaqlite_vec_len(&p->macro.layers) - 1; + p->ctx.layer_id = syntaqlite_vec_len(&p->rewrites.layers) - 1; // Attach captured arg spans to the fresh layer and flag it as a // fallback. scan_macro_args returns source-absolute offsets; // begin_macro_expansion rebases top-level call_offset to // statement-relative, so apply the same shift to the arg spans. - SynqExpansionLayer* lyr = &p->macro.layers.data[p->ctx.layer_id]; + SynqExpansionLayer* lyr = &p->rewrites.layers.data[p->ctx.layer_id]; lyr->is_fallback = 1; if (arg_count > 0 && arg_count <= SYNQ_FALLBACK_ARG_STACK_CAP) { SynqMacroArg* heap = p->mem.xMalloc(arg_count * sizeof(SynqMacroArg)); @@ -9396,7 +9673,7 @@ SYNTAQLITE_API int syntaqlite_macro_expansion_expand_and_set_result( // Steal the scratch vec's buffer directly into the layer (no copy). // Null-terminate for safety. syntaqlite_vec_push(&p->macro.expand_buf, 0, p->mem); - SynqExpansionLayer* lyr = &p->macro.layers.data[p->macro.pending_layer]; + SynqExpansionLayer* lyr = &p->rewrites.layers.data[p->macro.pending_layer]; layer_free_data(p, lyr); lyr->expansion_data = (const char*)p->macro.expand_buf.data; lyr->expansion_len = p->macro.expand_buf.count - 1; // exclude NUL @@ -9413,7 +9690,7 @@ SYNTAQLITE_API int syntaqlite_macro_expansion_expand_and_set_result( const char* origin_base = origin_layer_id == 0 ? p->stmt_source - : p->macro.layers.data[origin_layer_id].expansion_data; + : p->rewrites.layers.data[origin_layer_id].expansion_data; SynqArgSegment* segs = p->mem.xMalloc(mapping_count * sizeof(SynqArgSegment)); @@ -9440,6 +9717,106 @@ SYNTAQLITE_API int syntaqlite_macro_expansion_expand_and_set_result( #endif /* !SYNTAQLITE_OMIT_RUNTIME */ /* ======== end: csrc/parser_macros.c ======== */ +/* ======== begin: csrc/parser_node_expansion.c ======== */ +#ifndef SYNTAQLITE_OMIT_RUNTIME +// Copyright 2025 The syntaqlite Authors. All rights reserved. +// Licensed under the Apache License, Version 2.0. + +// Node expansion lets the grammar mark a node for the host to replace with its +// own text. The host expands the marked nodes once their statement is parsed, +// so it sees the whole statement, and each replacement is recorded as a +// rewrite next to macro calls, so it works everywhere they do. + +#include +#include + + +#ifndef SYNTAQLITE_OMIT_MACROS + +SYNTAQLITE_API int32_t +syntaqlite_parser_set_node_expander(SyntaqliteParser* p, + SyntaqliteNodeExpandFn fn, + void* user_data) { + p->node_expansion.expander = fn; + p->node_expansion.user_data = user_data; + return SYNTAQLITE_OK; +} + +SYNTAQLITE_API void syntaqlite_node_expansion_set_result(SyntaqliteParser* p, + const char* text, + SyntaqliteLength len) { + SynqNodeExpansionState* s = &p->node_expansion; + if (s->result) + p->mem.xFree(s->result); + s->result = p->mem.xMalloc(len + 1); + memcpy(s->result, text, len); + s->result[len] = '\0'; + s->result_len = len; +} + +// Expands the nodes the statement marked. Returns 0 if one fails, with the +// parser's error set. +static int synq_expand_marked_nodes(SyntaqliteParser* p) { + SynqNodeExpansionState* s = &p->node_expansion; + if (!s->expander) + return 1; + // Marked in the order they were parsed, so a node inside another is + // expanded first. + for (uint32_t i = 0; i < syntaqlite_vec_len(&p->ctx.marked_nodes); i++) { + SynqMarkedNode node = syntaqlite_vec_at(&p->ctx.marked_nodes, i); + uint32_t home = 0; + uint32_t start = 0; + uint32_t end = 0; + int ok = synq_node_site(p, node.node_id, &home, &start, &end) && + s->expander(s->user_data, p, node.node_id) == + SYNTAQLITE_NODE_EXPAND_OK && + s->result; + if (!ok) { + if (s->result) + p->mem.xFree(s->result); + s->result = NULL; + if (p->error_msg[0] == '\0') { + snprintf(p->error_msg, sizeof(p->error_msg), "expanding %.*s failed", + (int)node.name_len, node.name); + } + return 0; + } + + // Recorded as a layer, like a macro call's, but never fed back into the + // parser. + uint32_t body_offset = 0; + uint32_t body_length = 0; + synq_body_call_range(&p->rewrites.layers.data[home], start, end - start, + &body_offset, &body_length); + SynqExpansionLayer layer = { + .expansion_data = s->result, + .expansion_len = s->result_len, + .call_offset = start, + .call_length = end - start, + .name = node.name, + .name_len = node.name_len, + .body_call_offset = body_offset, + .body_call_length = body_length, + .parent_layer_id = home, + .kind = SYNTAQLITE_REWRITE_NODE_EXPANSION, + }; + syntaqlite_vec_push(&p->rewrites.layers, layer, p->mem); + s->result = NULL; + } + return 1; +} + +int synq_parser_expand_nodes(SyntaqliteParser* p) { + int ok = synq_expand_marked_nodes(p); + // Each marked node is expanded at most once, whether or not all were. + syntaqlite_vec_clear(&p->ctx.marked_nodes); + return ok; +} + +#endif // !SYNTAQLITE_OMIT_MACROS +#endif /* !SYNTAQLITE_OMIT_RUNTIME */ +/* ======== end: csrc/parser_node_expansion.c ======== */ + /* ======== begin: csrc/parser_spans.c ======== */ #ifndef SYNTAQLITE_OMIT_RUNTIME // Copyright 2025 The syntaqlite Authors. All rights reserved. @@ -9496,14 +9873,14 @@ static void span_walk_to_source(SyntaqliteParser* p, uint32_t off = offset; uint32_t len = length; uint32_t layer = layer_id; - uint32_t layers_count = syntaqlite_vec_len(&p->macro.layers); + uint32_t layers_count = syntaqlite_vec_len(&p->rewrites.layers); // Each iteration either drills into an arg origin layer or moves up // to a parent layer; cap defensively at twice the max depth. for (uint32_t step = 0; step < 2 * (SYNQ_MAX_MACRO_DEPTH + 1); step++) { if (layer == 0 || layer >= layers_count) { break; } - const SynqExpansionLayer* cur = &p->macro.layers.data[layer]; + const SynqExpansionLayer* cur = &p->rewrites.layers.data[layer]; // Arg-segment drill: if the span lies fully inside a substituted arg, // the authored bytes live in the segment's origin layer, not via the @@ -9529,11 +9906,11 @@ SYNTAQLITE_API const char* syntaqlite_parser_span_expanded_text( return NULL; } uint32_t layer = span->_layer_id; - if (layer >= syntaqlite_vec_len(&p->macro.layers)) { + if (layer >= syntaqlite_vec_len(&p->rewrites.layers)) { *out_len = 0; return NULL; } - const SynqExpansionLayer* lyr = &p->macro.layers.data[layer]; + const SynqExpansionLayer* lyr = &p->rewrites.layers.data[layer]; if (!lyr->expansion_data || span->offset + span->length > lyr->expansion_len) { *out_len = 0; @@ -9632,7 +10009,7 @@ SYNTAQLITE_API const SyntaqliteTracebackFrame* syntaqlite_parser_traceback( *out_count = 0; // Clear the scratch buffer from any previous call. Keeps the // allocation so repeat calls reuse the same heap block. - syntaqlite_vec_clear(&p->macro.traceback_buf); + syntaqlite_vec_clear(&p->rewrites.traceback_buf); if (!sp || sp->length == 0) return NULL; @@ -9644,14 +10021,14 @@ SYNTAQLITE_API const SyntaqliteTracebackFrame* syntaqlite_parser_traceback( uint32_t off = sp->offset; uint32_t len = sp->length; uint32_t layer_id = sp->_layer_id; - uint32_t layers_count = syntaqlite_vec_len(&p->macro.layers); + uint32_t layers_count = syntaqlite_vec_len(&p->rewrites.layers); for (uint32_t step = 0; step < 2 * (SYNQ_MAX_MACRO_DEPTH + 1) && count < SYNQ_MAX_MACRO_DEPTH + 2; step++) { if (layer_id >= layers_count) break; - const SynqExpansionLayer* lyr = &p->macro.layers.data[layer_id]; + const SynqExpansionLayer* lyr = &p->rewrites.layers.data[layer_id]; if (layer_id == 0) { // Root (sentinel) — emit final frame and terminate. @@ -9696,14 +10073,14 @@ SYNTAQLITE_API const SyntaqliteTracebackFrame* syntaqlite_parser_traceback( return NULL; // Reverse into the parser's owned buffer so frame[0] is outermost. - syntaqlite_vec_ensure(&p->macro.traceback_buf, count, p->mem); + syntaqlite_vec_ensure(&p->rewrites.traceback_buf, count, p->mem); for (uint32_t i = 0; i < count; i++) { - p->macro.traceback_buf.data[i] = tmp[count - 1 - i]; + p->rewrites.traceback_buf.data[i] = tmp[count - 1 - i]; } - p->macro.traceback_buf.count = count; + p->rewrites.traceback_buf.count = count; if (out_count) *out_count = count; - return p->macro.traceback_buf.data; + return p->rewrites.traceback_buf.data; } #endif // !SYNTAQLITE_OMIT_MACROS diff --git a/src/perfetto_sql/syntaqlite/syntaqlite_perfetto.h b/src/perfetto_sql/syntaqlite/syntaqlite_perfetto.h index 40befe078a5..409fde776d4 100644 --- a/src/perfetto_sql/syntaqlite/syntaqlite_perfetto.h +++ b/src/perfetto_sql/syntaqlite/syntaqlite_perfetto.h @@ -874,7 +874,7 @@ SYNTAQLITE_API int32_t syntaqlite_parser_set_trace(SyntaqliteParser* p, // Enable macro fallback: when the dialect uses SYNQ_MACRO_STYLE_RUST and a // name!(args) call is encountered but the name is NOT in the macro registry, // consume the entire name!(args) as a single TK_ID token instead of raising -// a parse error. A MacroRewrite is recorded so the formatter can emit the +// a parse error. A Rewrite is recorded so the formatter can emit the // call verbatim. Default: off (0). // Returns SYNTAQLITE_OK on success, SYNTAQLITE_ERR_ALREADY_USED if the // parser has already been used, SYNTAQLITE_ERR_OMITTED if macros are @@ -1048,26 +1048,37 @@ SYNTAQLITE_API const SyntaqliteComment* syntaqlite_node_trailing_comments( uint32_t node_id, uint32_t* count); -// Sentinel value for `SyntaqliteMacroRewrite::parent_idx` meaning "this +// Sentinel value for `SyntaqliteRewrite::parent_idx` meaning "this // rewrite applies directly to the authored source" (i.e. the rewrite is -// not nested inside another macro's expansion). -#define SYNTAQLITE_MACRO_PARENT_SOURCE UINT32_MAX +// not nested inside another rewrite's expansion). +#define SYNTAQLITE_REWRITE_PARENT_SOURCE UINT32_MAX -// Sentinel value for `SyntaqliteMacroRewrite::body_call_offset` and +// Sentinel value for `SyntaqliteRewrite::body_call_offset` and // `body_call_length` meaning "this call was tokenized from a $param // substitution — it has no position in the parent's authored body; // consumers should descend through the matching arg segment instead." #define SYNTAQLITE_MACRO_BODY_CALL_ARG_INTERNAL UINT32_MAX -// A recorded macro invocation — enough information to reconstruct a -// source-to-expanded rewrite tree (e.g. to drive Perfetto's +// The kind of thing a rewrite replaced. +typedef enum SyntaqliteRewriteKind { + // A `name!(...)` macro call, replaced by the macro's expansion. + SYNTAQLITE_REWRITE_MACRO_CALL = 0, + // A parsed node, replaced by text from the host's node expander (see + // `syntaqlite_parser_set_node_expander`). + SYNTAQLITE_REWRITE_NODE_EXPANSION = 1, +} SyntaqliteRewriteKind; + +// A rewrite recorded during parsing: a range of text replaced by other text, +// either a macro call or an expanded node (see `kind`). Enough information +// to reconstruct a source-to-expanded rewrite tree (e.g. to drive Perfetto's // SqlSource::Rewriter or an equivalent). // -// Entries are reported in insertion order: outer macros appear before the -// nested macros they contain, and macros at the same nesting level appear -// in source order. +// Entries are reported in insertion order. Macro calls come first: outer +// calls before the calls nested in them, and calls at the same nesting level +// in source order. Expanded nodes come after, innermost first, so a node's +// rewrite comes after the rewrites of the macro calls written inside it. // -// `parent_idx` is either SYNTAQLITE_MACRO_PARENT_SOURCE (the rewrite +// `parent_idx` is either SYNTAQLITE_REWRITE_PARENT_SOURCE (the rewrite // replaces a range in the authored source) or the index of another entry // in this same flat list (the rewrite replaces a range in that entry's // `expansion` buffer). @@ -1091,9 +1102,9 @@ SYNTAQLITE_API const SyntaqliteComment* syntaqlite_node_trailing_comments( // Pointers (`expansion`, `name`) are owned by the parser and remain valid // until the next `syntaqlite_parser_next`, `syntaqlite_parser_reset`, or // `syntaqlite_parser_destroy` call. -typedef struct SyntaqliteMacroRewrite { +typedef struct SyntaqliteRewrite { uint32_t parent_idx; - // Statement-relative when parent_idx == SYNTAQLITE_MACRO_PARENT_SOURCE, + // Statement-relative when parent_idx == SYNTAQLITE_REWRITE_PARENT_SOURCE, // otherwise relative to the parent entry's `expansion` buffer. SyntaqliteLayerOffset call_offset; SyntaqliteLength call_length; @@ -1110,14 +1121,14 @@ typedef struct SyntaqliteMacroRewrite { // text (no meaningful body position) and consumers should descend // through the matching arg segment instead. // - // For top-level rewrites (parent_idx == SYNTAQLITE_MACRO_PARENT_SOURCE) + // For top-level rewrites (parent_idx == SYNTAQLITE_REWRITE_PARENT_SOURCE) // the parent is the authored source, so these equal call_offset / // call_length. SyntaqliteLayerOffset body_call_offset; SyntaqliteLength body_call_length; // The buffer the `call_offset` — and every arg offset returned by // syntaqlite_macro_rewrite_arg_at — indexes into. For top-level - // rewrites (parent_idx == SYNTAQLITE_MACRO_PARENT_SOURCE) this is + // rewrites (parent_idx == SYNTAQLITE_REWRITE_PARENT_SOURCE) this is // the current statement source slice; for nested rewrites it is // the parent entry's `expansion` buffer. Consumers can slice the // call text as `parent_buffer + call_offset` and the arg texts @@ -1133,15 +1144,20 @@ typedef struct SyntaqliteMacroRewrite { // also a useful tell (0 for fallback), but this flag is the // authoritative signal. uint32_t is_fallback; -} SyntaqliteMacroRewrite; + // A SyntaqliteRewriteKind. For node expansions, the call is the node's text + // and the expansion is the host's replacement; macro-specific fields other + // than `name` are zero. Macro calls inside the node are still recorded, but + // when rewrites are applied the outer one wins. + uint32_t kind; +} SyntaqliteRewrite; -// Number of macro rewrites recorded for the current statement. -SYNTAQLITE_API uint32_t syntaqlite_result_macro_count(SyntaqliteParser* p); +// Number of rewrites recorded for the current statement. +SYNTAQLITE_API uint32_t syntaqlite_result_rewrite_count(SyntaqliteParser* p); // Returns the rewrite at `idx` (0-based). Returns a zero-initialized -// struct if `idx >= syntaqlite_result_macro_count(p)`. -SYNTAQLITE_API SyntaqliteMacroRewrite -syntaqlite_result_macro_rewrite_at(SyntaqliteParser* p, uint32_t idx); +// struct if `idx >= syntaqlite_result_rewrite_count(p)`. +SYNTAQLITE_API SyntaqliteRewrite +syntaqlite_result_rewrite_at(SyntaqliteParser* p, uint32_t idx); // One $param substitution within a macro expansion. // @@ -1154,7 +1170,7 @@ syntaqlite_result_macro_rewrite_at(SyntaqliteParser* p, uint32_t idx); // // `origin_parent_idx` + `origin_offset` + `origin_length` locate the // arg text where it was authored — either in the original source -// (`origin_parent_idx == SYNTAQLITE_MACRO_PARENT_SOURCE`) or in another +// (`origin_parent_idx == SYNTAQLITE_REWRITE_PARENT_SOURCE`) or in another // rewrite's `expansion` buffer (rewrite index). Consumers walk the // chain of $param substitutions by recursing into the origin rewrite's // arg segments. @@ -1402,6 +1418,34 @@ static inline int syntaqlite_span_is_macro_free( // // Requires `syntaqlite_parser_set_collect_node_extents(p, 1)` before the // first `reset()`. +// Where a node was written: the layer containing it and the node's range in +// that layer. +// +// The layer is the innermost one containing both the node's first and last +// tokens. If some of the node's tokens come from macro calls in that layer, the +// range covers those calls, so it's always a contiguous piece of the layer's +// text. +typedef struct SyntaqliteNodeSite { + // The rewrite whose expansion contains the node, or + // SYNTAQLITE_REWRITE_PARENT_SOURCE if the node is in the statement's own + // text. + uint32_t parent_idx; + // Uses the same coordinates as a rewrite's `call_offset`: relative to the + // statement for the source, otherwise relative to the parent's expansion. + SyntaqliteLayerOffset offset; + SyntaqliteLength length; +} SyntaqliteNodeSite; + +// Looks up where `node_id` was written and stores it in `*out`. Returns 1 on +// success, or 0 if node extents aren't being collected or the node has no +// tokens. +// +// Requires `syntaqlite_parser_set_collect_node_extents(p, 1)` before the +// first `reset()`. +SYNTAQLITE_API int syntaqlite_parser_node_site(SyntaqliteParser* p, + uint32_t node_id, + SyntaqliteNodeSite* out); + SYNTAQLITE_API int syntaqlite_node_is_macro_free(SyntaqliteParser* p, uint32_t node_id); @@ -1652,8 +1696,8 @@ SYNTAQLITE_API SyntaqliteDialect syntaqlite_sqlite_dialect(void); // done: // syntaqlite_parser_destroy(p); // -// Read accumulated macro rewrites via syntaqlite_result_macro_count() / -// syntaqlite_result_macro_rewrite_at() after parsing. +// Read accumulated rewrites via syntaqlite_result_rewrite_count() / +// syntaqlite_result_rewrite_at() after parsing. @@ -1727,6 +1771,50 @@ syntaqlite_parser_set_macro_lookup(SyntaqliteParser* p, SyntaqliteMacroLookupFn fn, void* user_data); +// --------------------------------------------------------------------------- +// Node expansion +// --------------------------------------------------------------------------- +// +// Macros replace text before it's parsed. Node expansion works the other way +// around: some dialect syntax is parsed as normal, then the host compiles it +// into SQL. The grammar marks which nodes this applies to and, once their +// statement is parsed, the host's expander replaces each of them. The host +// sees the whole statement while it does, such as the CTEs a node can read. +// +// The replacement is recorded as a rewrite (see +// `syntaqlite_result_rewrite_at`), just like a macro call, so it also works +// inside macro bodies and arguments. The replacement is never parsed: the AST +// keeps the original node. + +// Return codes for SyntaqliteNodeExpandFn callbacks. +#define SYNTAQLITE_NODE_EXPAND_OK 0 +#define SYNTAQLITE_NODE_EXPAND_ERROR (-1) + +// Called for each node the grammar marked, once the statement is parsed, so +// the whole statement can be read; a node inside another is expanded first. +// It should call `syntaqlite_node_expansion_set_result` and return +// SYNTAQLITE_NODE_EXPAND_OK, or return SYNTAQLITE_NODE_EXPAND_ERROR to fail the +// statement. +typedef int (*SyntaqliteNodeExpandFn)(void* user_data, + SyntaqliteParser* parser, + uint32_t node_id); + +// Sets the callback which expands nodes the grammar marks. Needs node extents +// (`syntaqlite_parser_set_collect_node_extents`), which place each node: +// without them every expansion fails its statement. Returns SYNTAQLITE_OK on +// success, or SYNTAQLITE_ERR_OMITTED if macros are compiled out, since node +// expansion needs the same rewrite machinery. +SYNTAQLITE_API int32_t +syntaqlite_parser_set_node_expander(SyntaqliteParser* p, + SyntaqliteNodeExpandFn fn, + void* user_data); + +// Sets the text to replace the current node with. Only call this from inside +// the expander callback. +SYNTAQLITE_API void syntaqlite_node_expansion_set_result(SyntaqliteParser* p, + const char* text, + SyntaqliteLength len); + // --------------------------------------------------------------------------- // Macro expansion result (called from inside the lookup callback) // --------------------------------------------------------------------------- diff --git a/src/trace_processor/perfetto_sql/parser/perfetto_sql_parser.cc b/src/trace_processor/perfetto_sql/parser/perfetto_sql_parser.cc index 580a864069e..dac2c12d178 100644 --- a/src/trace_processor/perfetto_sql/parser/perfetto_sql_parser.cc +++ b/src/trace_processor/perfetto_sql/parser/perfetto_sql_parser.cc @@ -137,12 +137,12 @@ class MacroRewriteBuilder { uint32_t stmt_doc_offset, const base::FlatHashMap& macros) : p_(p), stmt_(stmt), stmt_doc_offset_(stmt_doc_offset), macros_(macros) { - uint32_t total = syntaqlite_result_macro_count(p_); + uint32_t total = syntaqlite_result_rewrite_count(p_); no_macros_ = (total == 0); children_.resize(total); for (uint32_t i = 0; i < total; i++) { - auto r = syntaqlite_result_macro_rewrite_at(p_, i); - if (r.parent_idx == SYNTAQLITE_MACRO_PARENT_SOURCE) { + auto r = syntaqlite_result_rewrite_at(p_, i); + if (r.parent_idx == SYNTAQLITE_REWRITE_PARENT_SOURCE) { source_rooted_.push_back(i); } else { children_[r.parent_idx].push_back(i); @@ -189,7 +189,7 @@ class MacroRewriteBuilder { uint32_t range_length) const { std::vector items; for (uint32_t idx : children) { - auto c = syntaqlite_result_macro_rewrite_at(p_, idx); + auto c = syntaqlite_result_rewrite_at(p_, idx); if (c.call_offset < range_offset) continue; if (c.call_offset + c.call_length > range_offset + range_length) @@ -202,7 +202,7 @@ class MacroRewriteBuilder { // Recursive case: the expansion of a single macro rewrite. SqlSource BuildForRewrite(uint32_t idx) const { - auto r = syntaqlite_result_macro_rewrite_at(p_, idx); + auto r = syntaqlite_result_rewrite_at(p_, idx); std::string_view name(r.name, r.name_len); if (const Macro* m = macros_.Find(name); m) return BuildForUserMacro(idx, *m); @@ -228,7 +228,7 @@ class MacroRewriteBuilder { SqlSource BuildForUserMacro(uint32_t idx, const Macro& m) const { std::vector items; for (uint32_t cidx : children_[idx]) { - auto c = syntaqlite_result_macro_rewrite_at(p_, cidx); + auto c = syntaqlite_result_rewrite_at(p_, cidx); if (c.body_call_length == SYNTAQLITE_MACRO_BODY_CALL_ARG_INTERNAL) continue; items.push_back({c.body_call_offset, @@ -273,7 +273,7 @@ class MacroRewriteBuilder { } // Returns the SqlSource for the byte range [offset, offset+length) inside - // `parent`'s text (`parent` is either SYNTAQLITE_MACRO_PARENT_SOURCE or + // `parent`'s text (`parent` is either SYNTAQLITE_REWRITE_PARENT_SOURCE or // a rewrite index). // // If that range lies inside a `$param` substitution of `parent`, the arg @@ -285,7 +285,7 @@ class MacroRewriteBuilder { SqlSource AuthoredSourceOf(uint32_t parent, uint32_t offset, uint32_t length) const { - if (parent == SYNTAQLITE_MACRO_PARENT_SOURCE) + if (parent == SYNTAQLITE_REWRITE_PARENT_SOURCE) return stmt_.Substr(offset + stmt_doc_offset_, length); uint32_t seg_count = syntaqlite_macro_rewrite_arg_segment_count(p_, parent); for (uint32_t i = 0; i < seg_count; i++) { @@ -298,7 +298,7 @@ class MacroRewriteBuilder { } } // Literal text in `parent`'s body - not from any $param. - auto r = syntaqlite_result_macro_rewrite_at(p_, parent); + auto r = syntaqlite_result_rewrite_at(p_, parent); return SqlSource::FromMacroExpansion( std::string(r.expansion + offset, length), std::string(r.name, r.name_len)); @@ -331,7 +331,7 @@ class MacroRewriteBuilder { bool no_macros_ = true; // children_[parent_idx] = rewrite indices whose `parent_idx` equals that. std::vector> children_; - // Rewrites whose parent is SYNTAQLITE_MACRO_PARENT_SOURCE. + // Rewrites whose parent is SYNTAQLITE_REWRITE_PARENT_SOURCE. std::vector source_rooted_; }; diff --git a/tools/install-build-deps b/tools/install-build-deps index c1ffee1197c..852302b0d68 100755 --- a/tools/install-build-deps +++ b/tools/install-build-deps @@ -515,33 +515,33 @@ BIGTRACE_DEPS = [ SYNTAQLITE_DEPS = [ Dependency( 'buildtools/syntaqlite.tgz', - 'https://github.com/LalitMaganti/syntaqlite/releases/download/v0.10.1/syntaqlite-linux-x64.tar.gz', - '469f20daaa88fb8b8abe8baa9d1ab3e0eadea2f67ede4ceb44fc71d7150a1018', + 'https://github.com/LalitMaganti/syntaqlite/releases/download/v0.12.1/syntaqlite-linux-x64.tar.gz', + 'b55c12f33c07ae4dc16ae66520b4d12cfa8e4383fb3edf83ede16c7fd95241ef', 'linux', 'x64'), Dependency( 'buildtools/syntaqlite.tgz', - 'https://github.com/LalitMaganti/syntaqlite/releases/download/v0.10.1/syntaqlite-linux-arm64.tar.gz', - 'df293ab3cf6b92143d7171cd48b68c9a3dc90b172b11b73815e65efa4c894a14', + 'https://github.com/LalitMaganti/syntaqlite/releases/download/v0.12.1/syntaqlite-linux-arm64.tar.gz', + '49ac24b916db7eece63984d5141f9f4aa16d83f7d2f86a33d46eca647f7bba98', 'linux', 'arm64'), Dependency( 'buildtools/syntaqlite.tgz', - 'https://github.com/LalitMaganti/syntaqlite/releases/download/v0.10.1/syntaqlite-macos-x64.tar.gz', - 'e7c534b5389381c8102c4258cbd6be0c2125ab52b6b8a879e33200c19edf538b', + 'https://github.com/LalitMaganti/syntaqlite/releases/download/v0.12.1/syntaqlite-macos-x64.tar.gz', + '6bd729aad0f89e0eac68cc52f8f85fc074e7d90c49aef9d668ff192470fa9c1a', 'darwin', 'x64'), Dependency( 'buildtools/syntaqlite.tgz', - 'https://github.com/LalitMaganti/syntaqlite/releases/download/v0.10.1/syntaqlite-macos-arm64.tar.gz', - '88155719ad989b2ea1866fe240e850e806cace80a5a29029cc218cd9a267830e', + 'https://github.com/LalitMaganti/syntaqlite/releases/download/v0.12.1/syntaqlite-macos-arm64.tar.gz', + 'c3ac266b2da0e7932a74e2d1bb222202b8a83db000195f4c7a5f1191eacf1934', 'darwin', 'arm64'), Dependency( 'buildtools/syntaqlite.zip', - 'https://github.com/LalitMaganti/syntaqlite/releases/download/v0.10.1/syntaqlite-windows-x64.zip', - '75ab52efe6b8c42ec1ffe5afb66086fedaaa3668f562d845d15fd3f4300707d4', + 'https://github.com/LalitMaganti/syntaqlite/releases/download/v0.12.1/syntaqlite-windows-x64.zip', + '56b31b499016d8135c4cc085c4ab7dc28f4ce220768db8a5452a4d667275dfd1', 'windows', 'x64'), Dependency( 'buildtools/syntaqlite.zip', - 'https://github.com/LalitMaganti/syntaqlite/releases/download/v0.10.1/syntaqlite-windows-arm64.zip', - '11126807326d26da1036cb798d5628883034ea306709c12e16a7974104625f05', + 'https://github.com/LalitMaganti/syntaqlite/releases/download/v0.12.1/syntaqlite-windows-arm64.zip', + 'f48a2ef7e683d15caca586976b61d1fc257bf4cd6aa407035a56a56c3f6d1400', 'windows', 'arm64'), ] diff --git a/ui/package.json b/ui/package.json index 5f551ae93c1..4fb6f058f16 100644 --- a/ui/package.json +++ b/ui/package.json @@ -32,7 +32,7 @@ "noice-json-rpc": "^1.2.0", "pako": "^2.1.0", "protobufjs": "^7.6.2", - "syntaqlite": "^0.10.1", + "syntaqlite": "https://registry.npmjs.org/syntaqlite/-/syntaqlite-0.12.1.tgz", "uuid": "^14.0.0", "zod": "^4.3.5" }, diff --git a/ui/pnpm-lock.yaml b/ui/pnpm-lock.yaml index 50bcb55a6df..f81ec8a146a 100644 --- a/ui/pnpm-lock.yaml +++ b/ui/pnpm-lock.yaml @@ -84,8 +84,8 @@ importers: specifier: ^7.6.2 version: 7.6.5 syntaqlite: - specifier: ^0.10.1 - version: 0.10.1 + specifier: https://registry.npmjs.org/syntaqlite/-/syntaqlite-0.12.1.tgz + version: https://registry.npmjs.org/syntaqlite/-/syntaqlite-0.12.1.tgz uuid: specifier: ^14.0.0 version: 14.0.1 @@ -1852,8 +1852,9 @@ packages: resolution: {integrity: sha512-JJoOEKTfL1urb1mDoEblhD9NhEbWmq9jHEMEnxoC4ujUaZ4itA8vKgwkFAyNClgxplLi9tsUKX+EduK0p/l7sg==} engines: {node: ^14.18.0 || >=16.0.0} - syntaqlite@0.10.1: - resolution: {integrity: sha512-mybLbqBWbCzL/msQeA9iPVcgU3dV8RJ98VlHSpmhx5y+Limk8hO15RWXx+zNjHtCpouJHdlegI39x1BU6Gl6nA==} + syntaqlite@https://registry.npmjs.org/syntaqlite/-/syntaqlite-0.12.1.tgz: + resolution: {integrity: sha512-h07XtcblMG1v9UOacRD9nIWm4OyZyKSmvwG/lYvDRKrwEwmksyVcpxGHwlEtdSswZ2B9LrqG32Hd45zWbuZxcQ==, tarball: https://registry.npmjs.org/syntaqlite/-/syntaqlite-0.12.1.tgz} + version: 0.12.1 tinybench@6.1.4: resolution: {integrity: sha512-9APumHG7r4yOk4X4WlkmE71aZcv1gvin1czO3OQ1U9iJcFA5Ja/ygyb0vPOVHTthFozUYs8CLoLUlM8grb2lTQ==} @@ -3626,7 +3627,7 @@ snapshots: '@pkgr/core': 0.1.2 tslib: 2.8.1 - syntaqlite@0.10.1: {} + syntaqlite@https://registry.npmjs.org/syntaqlite/-/syntaqlite-0.12.1.tgz: {} tinybench@6.1.4: {}