Return groups - #418

Draft
gabriel-barrett wants to merge 13 commits into
mainfrom
return-groups
Draft

Return groups#418
gabriel-barrett wants to merge 13 commits into
mainfrom
return-groups

Conversation

@gabriel-barrett

Copy link
Copy Markdown
Member

Before return groups, each Aiur function compiled to a single circuit covering all return paths. This means that if a circuit has cold paths, it contributes to the cost of the hot paths. With return groups you're able to annotate the paths that you want to be bundled in the same circuit, say have a dedicated circuit for each hot path and a single circuit for all cold paths

@gabriel-barrett
gabriel-barrettforce-pushed the return-groups branch 3 times, most recently from 605a393 to 2e71e27CompareMay 20, 2026 01:04
gabriel-barrettand others added 4 commits May 20, 2026 13:41
Lean now owns return-group splitting and layout recompute. Adds
`Bytecode.Function.split` (with `returnGroups`/`filterGroup`/`fix`)
and `Toplevel.computeFiltered`, populated in `Source.Toplevel.compile`
after dedup + needsCircuit. Layout recompute reuses the existing
`Compiler.Layout.blockLayout`.
`Bytecode.Toplevel` gains `filteredFunctions : Array (Array (String ×
Function))`. The Rust FFI decoder reads it straight from Lean and
interns group names into `Arc<str>` shared across every `Ctrl::Return`
and every `filtered_functions` key.
Deletes the Rust duplicates (`src/aiur/split.rs`, `src/aiur/layout.rs`)
so there is one source of truth for bytecode shape.
Tests: adds `shared_return_groups` exercising two arms sharing `even`,
two sharing `odd`, and one unannotated (`""`) arm, aggregated into a
single entry `shared_return_groups_all` so the STARK suite proves
every group circuit in one run.
Source / Typed / Concrete / Simple keep `#[return_group(name)]` as a
`String` (user-written labels). At lowering time `Concrete.Function.compile`
allocates a `USize` per distinct group name in encounter order, stores the
table in `Bytecode.Function.groupNames`, and stamps every `Ctrl.return` with
the index. `Bytecode.Toplevel.filteredFunctions` becomes
`Array (Array Function)` keyed positionally by group index.
Rust mirrors: `Ctrl::Return(SelIdx, usize, Vec<ValIdx>)`,
`Toplevel.filtered_functions: Vec<Vec<Function>>`,
`QueryResult.return_group: usize`. The `Arc<str>` interner is gone — group
identity is now a `Copy` integer. `LeanAiurCtrl` is declared with
`num_usize: 1` on the `return` ctor so `get_usize(0)` is bounds-checked.
`LeanAiurFunction` bumps `num_obj: 2 → 3` to carry `groupNames`; the Rust
decoder reads it Lean-side only (display lookup in `Statistics`).
Execute ships `(groupIdx, width, rows, hits)` quads instead of name strings;
`Statistics.computeStats` resolves the display name via
`t.functions[i].groupNames[groupIdx]`.
Replace the anonymous `Nat × Nat × Nat × Nat` quads / `Nat × Nat` pairs
shipped from the executor with `GroupStats { groupIdx, totalWidth,
uniqueRows, totalHits }` and `MemoryCount { uniqueRows, totalHits }`,
bundled into a `QueryCounts { functionStats, memoryCounts }` struct.
The FFI extern keeps the tuple shape (so the Rust side can build it
without matching a Lean structure ctor); `Bytecode.Toplevel.execute`
converts to the structured form at the public API boundary. Callers
(`Kernel.lean`, `Statistics.computeStats`) lose the `.1`/`.2.2.1`
indexing and use named field access.
Two sites dropped the per-function `groupNames` table:
1. `Dedup.deduplicate_newFunctions` rebuilt the `Function` struct as
`{ body, layout, entry, constrained }`, letting the field default
`:= #[""]` collapse the table to a singleton. Every dedup'd function
then split into one group at idx 0, so multi-group stats showed a
single row instead of one per path.
2. `Lower.addCase` snapshotted the compiler state per arm and restored
`initState` (patching only `selIdx`). Allocations made by
`allocCurrentGroup` inside the arm — pushes to `groupNames` /
`groupNameMap` — were discarded, so every arm reused index 0 and the
final table held only the surviving allocation.
Fix: thread `groupNames`/`groupNameMap` through both rollbacks. Verified
via `lake exe kernel Nat.add_comm` with three return-group annotations
on `blake3_compress_chunks` — stats now show one row per split.
@gabriel-barrett
gabriel-barrett marked this pull request as draft May 20, 2026 20:24
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@gabriel-barrett@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Return groups - #418

Draft
gabriel-barrett wants to merge 13 commits into
mainfrom
return-groups
Draft

Return groups#418
gabriel-barrett wants to merge 13 commits into
mainfrom
return-groups

Conversation

@gabriel-barrett

Copy link
Copy Markdown
Member

Before return groups, each Aiur function compiled to a single circuit covering all return paths. This means that if a circuit has cold paths, it contributes to the cost of the hot paths. With return groups you're able to annotate the paths that you want to be bundled in the same circuit, say have a dedicated circuit for each hot path and a single circuit for all cold paths

@gabriel-barrett
gabriel-barrettforce-pushed the return-groups branch 3 times, most recently from 605a393 to 2e71e27CompareMay 20, 2026 01:04
gabriel-barrettand others added 4 commits May 20, 2026 13:41
Lean now owns return-group splitting and layout recompute. Adds
`Bytecode.Function.split` (with `returnGroups`/`filterGroup`/`fix`)
and `Toplevel.computeFiltered`, populated in `Source.Toplevel.compile`
after dedup + needsCircuit. Layout recompute reuses the existing
`Compiler.Layout.blockLayout`.
`Bytecode.Toplevel` gains `filteredFunctions : Array (Array (String ×
Function))`. The Rust FFI decoder reads it straight from Lean and
interns group names into `Arc<str>` shared across every `Ctrl::Return`
and every `filtered_functions` key.
Deletes the Rust duplicates (`src/aiur/split.rs`, `src/aiur/layout.rs`)
so there is one source of truth for bytecode shape.
Tests: adds `shared_return_groups` exercising two arms sharing `even`,
two sharing `odd`, and one unannotated (`""`) arm, aggregated into a
single entry `shared_return_groups_all` so the STARK suite proves
every group circuit in one run.
Source / Typed / Concrete / Simple keep `#[return_group(name)]` as a
`String` (user-written labels). At lowering time `Concrete.Function.compile`
allocates a `USize` per distinct group name in encounter order, stores the
table in `Bytecode.Function.groupNames`, and stamps every `Ctrl.return` with
the index. `Bytecode.Toplevel.filteredFunctions` becomes
`Array (Array Function)` keyed positionally by group index.
Rust mirrors: `Ctrl::Return(SelIdx, usize, Vec<ValIdx>)`,
`Toplevel.filtered_functions: Vec<Vec<Function>>`,
`QueryResult.return_group: usize`. The `Arc<str>` interner is gone — group
identity is now a `Copy` integer. `LeanAiurCtrl` is declared with
`num_usize: 1` on the `return` ctor so `get_usize(0)` is bounds-checked.
`LeanAiurFunction` bumps `num_obj: 2 → 3` to carry `groupNames`; the Rust
decoder reads it Lean-side only (display lookup in `Statistics`).
Execute ships `(groupIdx, width, rows, hits)` quads instead of name strings;
`Statistics.computeStats` resolves the display name via
`t.functions[i].groupNames[groupIdx]`.
Replace the anonymous `Nat × Nat × Nat × Nat` quads / `Nat × Nat` pairs
shipped from the executor with `GroupStats { groupIdx, totalWidth,
uniqueRows, totalHits }` and `MemoryCount { uniqueRows, totalHits }`,
bundled into a `QueryCounts { functionStats, memoryCounts }` struct.
The FFI extern keeps the tuple shape (so the Rust side can build it
without matching a Lean structure ctor); `Bytecode.Toplevel.execute`
converts to the structured form at the public API boundary. Callers
(`Kernel.lean`, `Statistics.computeStats`) lose the `.1`/`.2.2.1`
indexing and use named field access.
Two sites dropped the per-function `groupNames` table:
1. `Dedup.deduplicate_newFunctions` rebuilt the `Function` struct as
`{ body, layout, entry, constrained }`, letting the field default
`:= #[""]` collapse the table to a singleton. Every dedup'd function
then split into one group at idx 0, so multi-group stats showed a
single row instead of one per path.
2. `Lower.addCase` snapshotted the compiler state per arm and restored
`initState` (patching only `selIdx`). Allocations made by
`allocCurrentGroup` inside the arm — pushes to `groupNames` /
`groupNameMap` — were discarded, so every arm reused index 0 and the
final table held only the surviving allocation.
Fix: thread `groupNames`/`groupNameMap` through both rollbacks. Verified
via `lake exe kernel Nat.add_comm` with three return-group annotations
on `blake3_compress_chunks` — stats now show one row per split.
@gabriel-barrett
gabriel-barrett marked this pull request as draft May 20, 2026 20:24
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@gabriel-barrett@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Return groups - #418

Draft
gabriel-barrett wants to merge 13 commits into
mainfrom
return-groups
Draft

Return groups#418
gabriel-barrett wants to merge 13 commits into
mainfrom
return-groups

Conversation

@gabriel-barrett

Copy link
Copy Markdown
Member

Before return groups, each Aiur function compiled to a single circuit covering all return paths. This means that if a circuit has cold paths, it contributes to the cost of the hot paths. With return groups you're able to annotate the paths that you want to be bundled in the same circuit, say have a dedicated circuit for each hot path and a single circuit for all cold paths

@gabriel-barrett
gabriel-barrettforce-pushed the return-groups branch 3 times, most recently from 605a393 to 2e71e27CompareMay 20, 2026 01:04
gabriel-barrettand others added 4 commits May 20, 2026 13:41
Lean now owns return-group splitting and layout recompute. Adds
`Bytecode.Function.split` (with `returnGroups`/`filterGroup`/`fix`)
and `Toplevel.computeFiltered`, populated in `Source.Toplevel.compile`
after dedup + needsCircuit. Layout recompute reuses the existing
`Compiler.Layout.blockLayout`.
`Bytecode.Toplevel` gains `filteredFunctions : Array (Array (String ×
Function))`. The Rust FFI decoder reads it straight from Lean and
interns group names into `Arc<str>` shared across every `Ctrl::Return`
and every `filtered_functions` key.
Deletes the Rust duplicates (`src/aiur/split.rs`, `src/aiur/layout.rs`)
so there is one source of truth for bytecode shape.
Tests: adds `shared_return_groups` exercising two arms sharing `even`,
two sharing `odd`, and one unannotated (`""`) arm, aggregated into a
single entry `shared_return_groups_all` so the STARK suite proves
every group circuit in one run.
Source / Typed / Concrete / Simple keep `#[return_group(name)]` as a
`String` (user-written labels). At lowering time `Concrete.Function.compile`
allocates a `USize` per distinct group name in encounter order, stores the
table in `Bytecode.Function.groupNames`, and stamps every `Ctrl.return` with
the index. `Bytecode.Toplevel.filteredFunctions` becomes
`Array (Array Function)` keyed positionally by group index.
Rust mirrors: `Ctrl::Return(SelIdx, usize, Vec<ValIdx>)`,
`Toplevel.filtered_functions: Vec<Vec<Function>>`,
`QueryResult.return_group: usize`. The `Arc<str>` interner is gone — group
identity is now a `Copy` integer. `LeanAiurCtrl` is declared with
`num_usize: 1` on the `return` ctor so `get_usize(0)` is bounds-checked.
`LeanAiurFunction` bumps `num_obj: 2 → 3` to carry `groupNames`; the Rust
decoder reads it Lean-side only (display lookup in `Statistics`).
Execute ships `(groupIdx, width, rows, hits)` quads instead of name strings;
`Statistics.computeStats` resolves the display name via
`t.functions[i].groupNames[groupIdx]`.
Replace the anonymous `Nat × Nat × Nat × Nat` quads / `Nat × Nat` pairs
shipped from the executor with `GroupStats { groupIdx, totalWidth,
uniqueRows, totalHits }` and `MemoryCount { uniqueRows, totalHits }`,
bundled into a `QueryCounts { functionStats, memoryCounts }` struct.
The FFI extern keeps the tuple shape (so the Rust side can build it
without matching a Lean structure ctor); `Bytecode.Toplevel.execute`
converts to the structured form at the public API boundary. Callers
(`Kernel.lean`, `Statistics.computeStats`) lose the `.1`/`.2.2.1`
indexing and use named field access.
Two sites dropped the per-function `groupNames` table:
1. `Dedup.deduplicate_newFunctions` rebuilt the `Function` struct as
`{ body, layout, entry, constrained }`, letting the field default
`:= #[""]` collapse the table to a singleton. Every dedup'd function
then split into one group at idx 0, so multi-group stats showed a
single row instead of one per path.
2. `Lower.addCase` snapshotted the compiler state per arm and restored
`initState` (patching only `selIdx`). Allocations made by
`allocCurrentGroup` inside the arm — pushes to `groupNames` /
`groupNameMap` — were discarded, so every arm reused index 0 and the
final table held only the surviving allocation.
Fix: thread `groupNames`/`groupNameMap` through both rollbacks. Verified
via `lake exe kernel Nat.add_comm` with three return-group annotations
on `blake3_compress_chunks` — stats now show one row per split.
@gabriel-barrett
gabriel-barrett marked this pull request as draft May 20, 2026 20:24
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@gabriel-barrett@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Return groups - #418

Draft
gabriel-barrett wants to merge 13 commits into
mainfrom
return-groups
Draft

Return groups#418
gabriel-barrett wants to merge 13 commits into
mainfrom
return-groups

Conversation

@gabriel-barrett

Copy link
Copy Markdown
Member

Before return groups, each Aiur function compiled to a single circuit covering all return paths. This means that if a circuit has cold paths, it contributes to the cost of the hot paths. With return groups you're able to annotate the paths that you want to be bundled in the same circuit, say have a dedicated circuit for each hot path and a single circuit for all cold paths

@gabriel-barrett
gabriel-barrettforce-pushed the return-groups branch 3 times, most recently from 605a393 to 2e71e27CompareMay 20, 2026 01:04
gabriel-barrettand others added 4 commits May 20, 2026 13:41
Lean now owns return-group splitting and layout recompute. Adds
`Bytecode.Function.split` (with `returnGroups`/`filterGroup`/`fix`)
and `Toplevel.computeFiltered`, populated in `Source.Toplevel.compile`
after dedup + needsCircuit. Layout recompute reuses the existing
`Compiler.Layout.blockLayout`.
`Bytecode.Toplevel` gains `filteredFunctions : Array (Array (String ×
Function))`. The Rust FFI decoder reads it straight from Lean and
interns group names into `Arc<str>` shared across every `Ctrl::Return`
and every `filtered_functions` key.
Deletes the Rust duplicates (`src/aiur/split.rs`, `src/aiur/layout.rs`)
so there is one source of truth for bytecode shape.
Tests: adds `shared_return_groups` exercising two arms sharing `even`,
two sharing `odd`, and one unannotated (`""`) arm, aggregated into a
single entry `shared_return_groups_all` so the STARK suite proves
every group circuit in one run.
Source / Typed / Concrete / Simple keep `#[return_group(name)]` as a
`String` (user-written labels). At lowering time `Concrete.Function.compile`
allocates a `USize` per distinct group name in encounter order, stores the
table in `Bytecode.Function.groupNames`, and stamps every `Ctrl.return` with
the index. `Bytecode.Toplevel.filteredFunctions` becomes
`Array (Array Function)` keyed positionally by group index.
Rust mirrors: `Ctrl::Return(SelIdx, usize, Vec<ValIdx>)`,
`Toplevel.filtered_functions: Vec<Vec<Function>>`,
`QueryResult.return_group: usize`. The `Arc<str>` interner is gone — group
identity is now a `Copy` integer. `LeanAiurCtrl` is declared with
`num_usize: 1` on the `return` ctor so `get_usize(0)` is bounds-checked.
`LeanAiurFunction` bumps `num_obj: 2 → 3` to carry `groupNames`; the Rust
decoder reads it Lean-side only (display lookup in `Statistics`).
Execute ships `(groupIdx, width, rows, hits)` quads instead of name strings;
`Statistics.computeStats` resolves the display name via
`t.functions[i].groupNames[groupIdx]`.
Replace the anonymous `Nat × Nat × Nat × Nat` quads / `Nat × Nat` pairs
shipped from the executor with `GroupStats { groupIdx, totalWidth,
uniqueRows, totalHits }` and `MemoryCount { uniqueRows, totalHits }`,
bundled into a `QueryCounts { functionStats, memoryCounts }` struct.
The FFI extern keeps the tuple shape (so the Rust side can build it
without matching a Lean structure ctor); `Bytecode.Toplevel.execute`
converts to the structured form at the public API boundary. Callers
(`Kernel.lean`, `Statistics.computeStats`) lose the `.1`/`.2.2.1`
indexing and use named field access.
Two sites dropped the per-function `groupNames` table:
1. `Dedup.deduplicate_newFunctions` rebuilt the `Function` struct as
`{ body, layout, entry, constrained }`, letting the field default
`:= #[""]` collapse the table to a singleton. Every dedup'd function
then split into one group at idx 0, so multi-group stats showed a
single row instead of one per path.
2. `Lower.addCase` snapshotted the compiler state per arm and restored
`initState` (patching only `selIdx`). Allocations made by
`allocCurrentGroup` inside the arm — pushes to `groupNames` /
`groupNameMap` — were discarded, so every arm reused index 0 and the
final table held only the surviving allocation.
Fix: thread `groupNames`/`groupNameMap` through both rollbacks. Verified
via `lake exe kernel Nat.add_comm` with three return-group annotations
on `blake3_compress_chunks` — stats now show one row per split.
@gabriel-barrett
gabriel-barrett marked this pull request as draft May 20, 2026 20:24
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@gabriel-barrett@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Return groups - #418

Draft
gabriel-barrett wants to merge 13 commits into
mainfrom
return-groups
Draft

Return groups#418
gabriel-barrett wants to merge 13 commits into
mainfrom
return-groups

Conversation

@gabriel-barrett

Copy link
Copy Markdown
Member

Before return groups, each Aiur function compiled to a single circuit covering all return paths. This means that if a circuit has cold paths, it contributes to the cost of the hot paths. With return groups you're able to annotate the paths that you want to be bundled in the same circuit, say have a dedicated circuit for each hot path and a single circuit for all cold paths

@gabriel-barrett
gabriel-barrettforce-pushed the return-groups branch 3 times, most recently from 605a393 to 2e71e27CompareMay 20, 2026 01:04
gabriel-barrettand others added 4 commits May 20, 2026 13:41
Lean now owns return-group splitting and layout recompute. Adds
`Bytecode.Function.split` (with `returnGroups`/`filterGroup`/`fix`)
and `Toplevel.computeFiltered`, populated in `Source.Toplevel.compile`
after dedup + needsCircuit. Layout recompute reuses the existing
`Compiler.Layout.blockLayout`.
`Bytecode.Toplevel` gains `filteredFunctions : Array (Array (String ×
Function))`. The Rust FFI decoder reads it straight from Lean and
interns group names into `Arc<str>` shared across every `Ctrl::Return`
and every `filtered_functions` key.
Deletes the Rust duplicates (`src/aiur/split.rs`, `src/aiur/layout.rs`)
so there is one source of truth for bytecode shape.
Tests: adds `shared_return_groups` exercising two arms sharing `even`,
two sharing `odd`, and one unannotated (`""`) arm, aggregated into a
single entry `shared_return_groups_all` so the STARK suite proves
every group circuit in one run.
Source / Typed / Concrete / Simple keep `#[return_group(name)]` as a
`String` (user-written labels). At lowering time `Concrete.Function.compile`
allocates a `USize` per distinct group name in encounter order, stores the
table in `Bytecode.Function.groupNames`, and stamps every `Ctrl.return` with
the index. `Bytecode.Toplevel.filteredFunctions` becomes
`Array (Array Function)` keyed positionally by group index.
Rust mirrors: `Ctrl::Return(SelIdx, usize, Vec<ValIdx>)`,
`Toplevel.filtered_functions: Vec<Vec<Function>>`,
`QueryResult.return_group: usize`. The `Arc<str>` interner is gone — group
identity is now a `Copy` integer. `LeanAiurCtrl` is declared with
`num_usize: 1` on the `return` ctor so `get_usize(0)` is bounds-checked.
`LeanAiurFunction` bumps `num_obj: 2 → 3` to carry `groupNames`; the Rust
decoder reads it Lean-side only (display lookup in `Statistics`).
Execute ships `(groupIdx, width, rows, hits)` quads instead of name strings;
`Statistics.computeStats` resolves the display name via
`t.functions[i].groupNames[groupIdx]`.
Replace the anonymous `Nat × Nat × Nat × Nat` quads / `Nat × Nat` pairs
shipped from the executor with `GroupStats { groupIdx, totalWidth,
uniqueRows, totalHits }` and `MemoryCount { uniqueRows, totalHits }`,
bundled into a `QueryCounts { functionStats, memoryCounts }` struct.
The FFI extern keeps the tuple shape (so the Rust side can build it
without matching a Lean structure ctor); `Bytecode.Toplevel.execute`
converts to the structured form at the public API boundary. Callers
(`Kernel.lean`, `Statistics.computeStats`) lose the `.1`/`.2.2.1`
indexing and use named field access.
Two sites dropped the per-function `groupNames` table:
1. `Dedup.deduplicate_newFunctions` rebuilt the `Function` struct as
`{ body, layout, entry, constrained }`, letting the field default
`:= #[""]` collapse the table to a singleton. Every dedup'd function
then split into one group at idx 0, so multi-group stats showed a
single row instead of one per path.
2. `Lower.addCase` snapshotted the compiler state per arm and restored
`initState` (patching only `selIdx`). Allocations made by
`allocCurrentGroup` inside the arm — pushes to `groupNames` /
`groupNameMap` — were discarded, so every arm reused index 0 and the
final table held only the surviving allocation.
Fix: thread `groupNames`/`groupNameMap` through both rollbacks. Verified
via `lake exe kernel Nat.add_comm` with three return-group annotations
on `blake3_compress_chunks` — stats now show one row per split.
@gabriel-barrett
gabriel-barrett marked this pull request as draft May 20, 2026 20:24
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@gabriel-barrett@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Return groups - #418

Draft
gabriel-barrett wants to merge 13 commits into
mainfrom
return-groups
Draft

Return groups#418
gabriel-barrett wants to merge 13 commits into
mainfrom
return-groups

Conversation

@gabriel-barrett

Copy link
Copy Markdown
Member

Before return groups, each Aiur function compiled to a single circuit covering all return paths. This means that if a circuit has cold paths, it contributes to the cost of the hot paths. With return groups you're able to annotate the paths that you want to be bundled in the same circuit, say have a dedicated circuit for each hot path and a single circuit for all cold paths

@gabriel-barrett
gabriel-barrettforce-pushed the return-groups branch 3 times, most recently from 605a393 to 2e71e27CompareMay 20, 2026 01:04
gabriel-barrettand others added 4 commits May 20, 2026 13:41
Lean now owns return-group splitting and layout recompute. Adds
`Bytecode.Function.split` (with `returnGroups`/`filterGroup`/`fix`)
and `Toplevel.computeFiltered`, populated in `Source.Toplevel.compile`
after dedup + needsCircuit. Layout recompute reuses the existing
`Compiler.Layout.blockLayout`.
`Bytecode.Toplevel` gains `filteredFunctions : Array (Array (String ×
Function))`. The Rust FFI decoder reads it straight from Lean and
interns group names into `Arc<str>` shared across every `Ctrl::Return`
and every `filtered_functions` key.
Deletes the Rust duplicates (`src/aiur/split.rs`, `src/aiur/layout.rs`)
so there is one source of truth for bytecode shape.
Tests: adds `shared_return_groups` exercising two arms sharing `even`,
two sharing `odd`, and one unannotated (`""`) arm, aggregated into a
single entry `shared_return_groups_all` so the STARK suite proves
every group circuit in one run.
Source / Typed / Concrete / Simple keep `#[return_group(name)]` as a
`String` (user-written labels). At lowering time `Concrete.Function.compile`
allocates a `USize` per distinct group name in encounter order, stores the
table in `Bytecode.Function.groupNames`, and stamps every `Ctrl.return` with
the index. `Bytecode.Toplevel.filteredFunctions` becomes
`Array (Array Function)` keyed positionally by group index.
Rust mirrors: `Ctrl::Return(SelIdx, usize, Vec<ValIdx>)`,
`Toplevel.filtered_functions: Vec<Vec<Function>>`,
`QueryResult.return_group: usize`. The `Arc<str>` interner is gone — group
identity is now a `Copy` integer. `LeanAiurCtrl` is declared with
`num_usize: 1` on the `return` ctor so `get_usize(0)` is bounds-checked.
`LeanAiurFunction` bumps `num_obj: 2 → 3` to carry `groupNames`; the Rust
decoder reads it Lean-side only (display lookup in `Statistics`).
Execute ships `(groupIdx, width, rows, hits)` quads instead of name strings;
`Statistics.computeStats` resolves the display name via
`t.functions[i].groupNames[groupIdx]`.
Replace the anonymous `Nat × Nat × Nat × Nat` quads / `Nat × Nat` pairs
shipped from the executor with `GroupStats { groupIdx, totalWidth,
uniqueRows, totalHits }` and `MemoryCount { uniqueRows, totalHits }`,
bundled into a `QueryCounts { functionStats, memoryCounts }` struct.
The FFI extern keeps the tuple shape (so the Rust side can build it
without matching a Lean structure ctor); `Bytecode.Toplevel.execute`
converts to the structured form at the public API boundary. Callers
(`Kernel.lean`, `Statistics.computeStats`) lose the `.1`/`.2.2.1`
indexing and use named field access.
Two sites dropped the per-function `groupNames` table:
1. `Dedup.deduplicate_newFunctions` rebuilt the `Function` struct as
`{ body, layout, entry, constrained }`, letting the field default
`:= #[""]` collapse the table to a singleton. Every dedup'd function
then split into one group at idx 0, so multi-group stats showed a
single row instead of one per path.
2. `Lower.addCase` snapshotted the compiler state per arm and restored
`initState` (patching only `selIdx`). Allocations made by
`allocCurrentGroup` inside the arm — pushes to `groupNames` /
`groupNameMap` — were discarded, so every arm reused index 0 and the
final table held only the surviving allocation.
Fix: thread `groupNames`/`groupNameMap` through both rollbacks. Verified
via `lake exe kernel Nat.add_comm` with three return-group annotations
on `blake3_compress_chunks` — stats now show one row per split.
@gabriel-barrett
gabriel-barrett marked this pull request as draft May 20, 2026 20:24
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@gabriel-barrett@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Return groups - #418

Draft
gabriel-barrett wants to merge 13 commits into
mainfrom
return-groups
Draft

Return groups#418
gabriel-barrett wants to merge 13 commits into
mainfrom
return-groups

Conversation

@gabriel-barrett

Copy link
Copy Markdown
Member

Before return groups, each Aiur function compiled to a single circuit covering all return paths. This means that if a circuit has cold paths, it contributes to the cost of the hot paths. With return groups you're able to annotate the paths that you want to be bundled in the same circuit, say have a dedicated circuit for each hot path and a single circuit for all cold paths

@gabriel-barrett
gabriel-barrettforce-pushed the return-groups branch 3 times, most recently from 605a393 to 2e71e27CompareMay 20, 2026 01:04
gabriel-barrettand others added 4 commits May 20, 2026 13:41
Lean now owns return-group splitting and layout recompute. Adds
`Bytecode.Function.split` (with `returnGroups`/`filterGroup`/`fix`)
and `Toplevel.computeFiltered`, populated in `Source.Toplevel.compile`
after dedup + needsCircuit. Layout recompute reuses the existing
`Compiler.Layout.blockLayout`.
`Bytecode.Toplevel` gains `filteredFunctions : Array (Array (String ×
Function))`. The Rust FFI decoder reads it straight from Lean and
interns group names into `Arc<str>` shared across every `Ctrl::Return`
and every `filtered_functions` key.
Deletes the Rust duplicates (`src/aiur/split.rs`, `src/aiur/layout.rs`)
so there is one source of truth for bytecode shape.
Tests: adds `shared_return_groups` exercising two arms sharing `even`,
two sharing `odd`, and one unannotated (`""`) arm, aggregated into a
single entry `shared_return_groups_all` so the STARK suite proves
every group circuit in one run.
Source / Typed / Concrete / Simple keep `#[return_group(name)]` as a
`String` (user-written labels). At lowering time `Concrete.Function.compile`
allocates a `USize` per distinct group name in encounter order, stores the
table in `Bytecode.Function.groupNames`, and stamps every `Ctrl.return` with
the index. `Bytecode.Toplevel.filteredFunctions` becomes
`Array (Array Function)` keyed positionally by group index.
Rust mirrors: `Ctrl::Return(SelIdx, usize, Vec<ValIdx>)`,
`Toplevel.filtered_functions: Vec<Vec<Function>>`,
`QueryResult.return_group: usize`. The `Arc<str>` interner is gone — group
identity is now a `Copy` integer. `LeanAiurCtrl` is declared with
`num_usize: 1` on the `return` ctor so `get_usize(0)` is bounds-checked.
`LeanAiurFunction` bumps `num_obj: 2 → 3` to carry `groupNames`; the Rust
decoder reads it Lean-side only (display lookup in `Statistics`).
Execute ships `(groupIdx, width, rows, hits)` quads instead of name strings;
`Statistics.computeStats` resolves the display name via
`t.functions[i].groupNames[groupIdx]`.
Replace the anonymous `Nat × Nat × Nat × Nat` quads / `Nat × Nat` pairs
shipped from the executor with `GroupStats { groupIdx, totalWidth,
uniqueRows, totalHits }` and `MemoryCount { uniqueRows, totalHits }`,
bundled into a `QueryCounts { functionStats, memoryCounts }` struct.
The FFI extern keeps the tuple shape (so the Rust side can build it
without matching a Lean structure ctor); `Bytecode.Toplevel.execute`
converts to the structured form at the public API boundary. Callers
(`Kernel.lean`, `Statistics.computeStats`) lose the `.1`/`.2.2.1`
indexing and use named field access.
Two sites dropped the per-function `groupNames` table:
1. `Dedup.deduplicate_newFunctions` rebuilt the `Function` struct as
`{ body, layout, entry, constrained }`, letting the field default
`:= #[""]` collapse the table to a singleton. Every dedup'd function
then split into one group at idx 0, so multi-group stats showed a
single row instead of one per path.
2. `Lower.addCase` snapshotted the compiler state per arm and restored
`initState` (patching only `selIdx`). Allocations made by
`allocCurrentGroup` inside the arm — pushes to `groupNames` /
`groupNameMap` — were discarded, so every arm reused index 0 and the
final table held only the surviving allocation.
Fix: thread `groupNames`/`groupNameMap` through both rollbacks. Verified
via `lake exe kernel Nat.add_comm` with three return-group annotations
on `blake3_compress_chunks` — stats now show one row per split.
@gabriel-barrett
gabriel-barrett marked this pull request as draft May 20, 2026 20:24
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@gabriel-barrett@arthurpaulino
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Return groups - #418

Draft
gabriel-barrett wants to merge 13 commits into
mainfrom
return-groups
Draft

Return groups#418
gabriel-barrett wants to merge 13 commits into
mainfrom
return-groups

Conversation

@gabriel-barrett

Copy link
Copy Markdown
Member

Before return groups, each Aiur function compiled to a single circuit covering all return paths. This means that if a circuit has cold paths, it contributes to the cost of the hot paths. With return groups you're able to annotate the paths that you want to be bundled in the same circuit, say have a dedicated circuit for each hot path and a single circuit for all cold paths

@gabriel-barrett
gabriel-barrettforce-pushed the return-groups branch 3 times, most recently from 605a393 to 2e71e27CompareMay 20, 2026 01:04
gabriel-barrettand others added 4 commits May 20, 2026 13:41
Lean now owns return-group splitting and layout recompute. Adds
`Bytecode.Function.split` (with `returnGroups`/`filterGroup`/`fix`)
and `Toplevel.computeFiltered`, populated in `Source.Toplevel.compile`
after dedup + needsCircuit. Layout recompute reuses the existing
`Compiler.Layout.blockLayout`.
`Bytecode.Toplevel` gains `filteredFunctions : Array (Array (String ×
Function))`. The Rust FFI decoder reads it straight from Lean and
interns group names into `Arc<str>` shared across every `Ctrl::Return`
and every `filtered_functions` key.
Deletes the Rust duplicates (`src/aiur/split.rs`, `src/aiur/layout.rs`)
so there is one source of truth for bytecode shape.
Tests: adds `shared_return_groups` exercising two arms sharing `even`,
two sharing `odd`, and one unannotated (`""`) arm, aggregated into a
single entry `shared_return_groups_all` so the STARK suite proves
every group circuit in one run.
Source / Typed / Concrete / Simple keep `#[return_group(name)]` as a
`String` (user-written labels). At lowering time `Concrete.Function.compile`
allocates a `USize` per distinct group name in encounter order, stores the
table in `Bytecode.Function.groupNames`, and stamps every `Ctrl.return` with
the index. `Bytecode.Toplevel.filteredFunctions` becomes
`Array (Array Function)` keyed positionally by group index.
Rust mirrors: `Ctrl::Return(SelIdx, usize, Vec<ValIdx>)`,
`Toplevel.filtered_functions: Vec<Vec<Function>>`,
`QueryResult.return_group: usize`. The `Arc<str>` interner is gone — group
identity is now a `Copy` integer. `LeanAiurCtrl` is declared with
`num_usize: 1` on the `return` ctor so `get_usize(0)` is bounds-checked.
`LeanAiurFunction` bumps `num_obj: 2 → 3` to carry `groupNames`; the Rust
decoder reads it Lean-side only (display lookup in `Statistics`).
Execute ships `(groupIdx, width, rows, hits)` quads instead of name strings;
`Statistics.computeStats` resolves the display name via
`t.functions[i].groupNames[groupIdx]`.
Replace the anonymous `Nat × Nat × Nat × Nat` quads / `Nat × Nat` pairs
shipped from the executor with `GroupStats { groupIdx, totalWidth,
uniqueRows, totalHits }` and `MemoryCount { uniqueRows, totalHits }`,
bundled into a `QueryCounts { functionStats, memoryCounts }` struct.
The FFI extern keeps the tuple shape (so the Rust side can build it
without matching a Lean structure ctor); `Bytecode.Toplevel.execute`
converts to the structured form at the public API boundary. Callers
(`Kernel.lean`, `Statistics.computeStats`) lose the `.1`/`.2.2.1`
indexing and use named field access.
Two sites dropped the per-function `groupNames` table:
1. `Dedup.deduplicate_newFunctions` rebuilt the `Function` struct as
`{ body, layout, entry, constrained }`, letting the field default
`:= #[""]` collapse the table to a singleton. Every dedup'd function
then split into one group at idx 0, so multi-group stats showed a
single row instead of one per path.
2. `Lower.addCase` snapshotted the compiler state per arm and restored
`initState` (patching only `selIdx`). Allocations made by
`allocCurrentGroup` inside the arm — pushes to `groupNames` /
`groupNameMap` — were discarded, so every arm reused index 0 and the
final table held only the surviving allocation.
Fix: thread `groupNames`/`groupNameMap` through both rollbacks. Verified
via `lake exe kernel Nat.add_comm` with three return-group annotations
on `blake3_compress_chunks` — stats now show one row per split.
@gabriel-barrett
gabriel-barrett marked this pull request as draft May 20, 2026 20:24
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@gabriel-barrett@arthurpaulino