feat(kernel): R7b Ruby walker — ruby module, tree-sitter-ruby 0.23.1 bump, ref-flag wire slot, ruby default-routed (#1379)
Third R7b port, checklist-first recipe (docs/design/ruby-kernel-port-checklist.md). Grammar bump first, validated standalone (the rust pattern): tree-sitter-ruby ^0.20.1 (tree-sitter-wasms, 2024-02) → v0.23.1 — crate pinned =0.23.1, wasm built from tag 71bd32f's checked-in parser.c/scanner.c (both sha-matched against the crates.io tarball; content bump, ABI stays 14). Old-vs-new full-init dumps: sinatra/jekyll byte-identical; rails = exactly the one classified hunk (the `recv&.!=` safe-nav operator misparse fix, `table_name.!` → `table_name.!=`, precision-positive). Walker (python.rs chassis + the six ruby divergences) preserves bug-for-bug: the importTypes:['call'] funnel (class-body DSL — attr_accessor, has_many, define_method incl. its block, sinatra route blocks — emits NOTHING at non-body scope), hook-handled module multiply-capture (nested modules re-scan their subtree per level after popping — `this.hooked` fn-refs from class AND module AND file), the sibling-scan visibility trio (bare `private` invisible; `private :sym`/`private def` poison all later defs; the inner def stays public), bare-call statements (do…end body_statement emits, brace-block block_body doesn't), `.new` instantiates with last-`::`-segment names, constant-receiver references refs, require/require_relative path refs (posix-normalized, `.rb`-suffixed, `Kernel.require` and interpolated-path quirks included), `=begin` docstring marker survival, and the reverse-order value-ref DFS. Wire v2: the hook's mixin `implements` refs carry `filePath: ctx.filePath` — the ONE extraction-ref denormalized field (php's trait-use refs share the shape). RefRow's first pad byte becomes a flags slot (REF_FLAG_FILE_PATH); decode re-attaches its own filePath parameter; KERNEL_ABI_VERSION 1→2 on both sides (mismatched dist/.node pairs degrade to wasm, as designed). Gates: sweeps 0-diff sinatra 147/147, jekyll 164/164, rails 3452/3452 (3,763 files, 0 deferrals — ruby error incidence 0.00%, any deferral = walker bug); full-init dumps byte-identical ×3 (7.2k/9.4k/375.6k lines); kernel-ruby-parity suite (torture + CRLF + wire-flag pin + defer) + ruby grammar-parity row; full suite 2,613 green ×2 under CODEGRAPH_KERNEL_EXPECT=1 (one unrelated mcp-initialize timing flake under parallel load, passes solo 3/3 ×3). DEFAULT_ROUTED += ruby (12 langs). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
286e9ccc2d
commit
1909931238
@@ -301,6 +301,11 @@ const VENDORED_WASM_LANGS: ReadonlySet<GrammarLanguage> = new Set([
|
||||
// parser.c/scanner.c sha-matched against the crates.io tarball. Replaces the
|
||||
// 2023-era tree-sitter-wasms build (ABI 14 → 15).
|
||||
'rust',
|
||||
// R7b (Ruby kernel port prep): tree-sitter-ruby v0.23.1 (71bd32f),
|
||||
// parser.c/scanner.c sha-matched against the crates.io tarball. Replaces the
|
||||
// ^0.20.1 tree-sitter-wasms build. Content bump only — the tag's checked-in
|
||||
// parser.c is still ABI 14 (predates the ABI-15 generator).
|
||||
'ruby',
|
||||
]);
|
||||
|
||||
/** Absolute path of a language's grammar WASM (vendored or tree-sitter-wasms). */
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
NONE,
|
||||
PROVENANCES,
|
||||
REF,
|
||||
REF_FLAG_FILE_PATH,
|
||||
REF_ROW_SIZE,
|
||||
VISIBILITIES,
|
||||
} from './layout';
|
||||
@@ -148,9 +149,13 @@ export function decodeExtractBuffers(
|
||||
const row = buffers.refs.subarray(i * REF_ROW_SIZE, (i + 1) * REF_ROW_SIZE);
|
||||
const fromIdx = row.readUInt32LE(REF.fromIdx);
|
||||
const kindByte = row.readUInt8(REF.kind);
|
||||
// No filePath/language here: the wasm extractors emit refs WITHOUT the
|
||||
// denormalized fields (the store fills them via `ref.filePath ?? filePath`),
|
||||
// and the kernel must match the extractFromSource seam exactly.
|
||||
// No filePath/language on ordinary refs: the wasm extractors emit them
|
||||
// WITHOUT the denormalized fields (the store fills `ref.filePath ??
|
||||
// filePath`), and the kernel must match the extractFromSource seam
|
||||
// exactly. The ONE exception is flagged (REF_FLAG_FILE_PATH): the
|
||||
// ruby/php visitNode hooks set `filePath: ctx.filePath` on their
|
||||
// mixin/trait `implements` refs — re-attach the decode call's own
|
||||
// filePath, which is that exact value.
|
||||
const ref: UnresolvedReference = {
|
||||
fromNodeId: fromIdx === NONE ? str(arena, row, REF.fromIdStr)! : idByRow[fromIdx]!,
|
||||
referenceName: str(arena, row, REF.referenceName)!,
|
||||
@@ -161,6 +166,7 @@ export function decodeExtractBuffers(
|
||||
line: row.readUInt32LE(REF.line),
|
||||
column: row.readUInt32LE(REF.column),
|
||||
};
|
||||
if ((row.readUInt8(REF.flags) & REF_FLAG_FILE_PATH) !== 0) ref.filePath = filePath;
|
||||
const candidates = strList(arena, row, REF.candidates);
|
||||
if (candidates !== undefined) ref.candidates = candidates;
|
||||
unresolvedReferences[i] = ref;
|
||||
|
||||
@@ -59,6 +59,11 @@ const DEFAULT_ROUTED: ReadonlySet<Language> = new Set<Language>([
|
||||
// Deferral 0.05–3.3% — both-branches-kept `#if` damage that errors on BOTH
|
||||
// arms (the preParse blanking hoist keeps the kernel's input identical).
|
||||
'csharp',
|
||||
// R7b (2026-07-20): parity swept 0-diff on sinatra/jekyll/rails (3,763
|
||||
// files byte-parity, 0 deferrals — ruby error incidence is 0.00%) +
|
||||
// full-init dump-diffs byte-identical ×3. Any deferral on a ruby sweep is
|
||||
// a walker-bug signal, not grammar reality.
|
||||
'ruby',
|
||||
]);
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* path instead of mis-decoding.
|
||||
*/
|
||||
|
||||
export const KERNEL_ABI_VERSION = 1;
|
||||
export const KERNEL_ABI_VERSION = 2;
|
||||
|
||||
/** Sentinel for "absent" in u32 slots and string-ref offsets. */
|
||||
export const NONE = 0xffffffff;
|
||||
@@ -77,6 +77,7 @@ export const EDGE = {
|
||||
export const REF = {
|
||||
fromIdx: 0, // u32 (NONE → fromIdStr)
|
||||
kind: 4, // u8 — EDGE_KINDS index, or FUNCTION_REF_CODE
|
||||
flags: 5, // u8 — REF_FLAGS bits (v2)
|
||||
line: 8, // u32
|
||||
column: 12, // u32
|
||||
referenceName: 16, // str
|
||||
@@ -87,6 +88,15 @@ export const REF = {
|
||||
/** ReferenceKind wire code for the internal-only `function_ref` (#756). */
|
||||
export const FUNCTION_REF_CODE = 200;
|
||||
|
||||
/**
|
||||
* Ref-row flag bits (v2). FILE_PATH: the ref carries `filePath` = the
|
||||
* extracted file — the ruby/php visitNode hooks set `filePath: ctx.filePath`
|
||||
* on their mixin/trait `implements` refs (unlike every other extraction ref,
|
||||
* which the store denormalizes); decode re-attaches its own filePath
|
||||
* parameter, which is byte-identical.
|
||||
*/
|
||||
export const REF_FLAG_FILE_PATH = 1;
|
||||
|
||||
/** Node bool-flag bit pairs: bit(2n) = present, bit(2n+1) = value. */
|
||||
export const FLAG = {
|
||||
isExported: 0,
|
||||
|
||||
Executable
BIN
Binary file not shown.
Reference in New Issue
Block a user