@@ -50,52 +50,69 @@ instance : BEq IOBuffer where
5050-- via `Std.HashMap.beq_iff_equiv` + `Std.HashMap.Equiv.{refl,symm,trans}`,
5151-- bypassing the need for `LawfulBEq` on the outer `IOBuffer`.
5252
53- /-- Per-circuit query counts for one circuit (one per function circuit, then
54- one per memory size). `uniqueRows` is the trace height; `totalHits` is the sum
55- of query multiplicities. The difference `totalHits - uniqueRows` is the number
56- of cache hits. -/
57- structure QueryCount where
53+ namespace Bytecode.Toplevel
54+
55+ /-- Per-split execution stats for one return-group of one function.
56+ `groupIdx` keys the corresponding entry in `Function.groupNames`. -/
57+ structure GroupStats where
58+ groupIdx : Nat
59+ totalWidth : Nat
5860 uniqueRows : Nat
5961 totalHits : Nat
60- deriving Inhabited
62+ deriving Inhabited, Repr
6163
62- namespace Bytecode.Toplevel
64+ /-- Per-memory-size counts. `uniqueRows` is the trace height; `totalHits`
65+ is the sum of multiplicities. `totalHits - uniqueRows` is the cache-hit
66+ count. -/
67+ structure MemoryCount where
68+ uniqueRows : Nat
69+ totalHits : Nat
70+ deriving Inhabited, Repr
6371
64- /-- Per-function execution stats. One entry per split (return group), keyed
65- by group index. Each quadruple is
66- `(groupIdx, totalWidth, uniqueRows, totalHits)`. The display name is looked
67- up via `Function.groupNames[groupIdx]`. -/
68- abbrev FunctionStats := Array (Array (Nat × Nat × Nat × Nat))
72+ /-- Per-function execution stats. Outer index is `FunIdx`; inner index is
73+ the `USize` group index used by `Ctrl.return`. -/
74+ abbrev FunctionStats := Array (Array GroupStats)
6975
70- /-- Per-memory-size `(uniqueRows, totalHits)` pairs . -/
71- abbrev MemoryCounts := Array (Nat × Nat)
76+ /-- Per-memory-size counts, parallel to `Toplevel.memorySizes` . -/
77+ abbrev MemoryCounts := Array MemoryCount
7278
73- /-- Query counts shipped back from the Rust executor: per-function split stats
74- plus per-memory pairs. -/
75- abbrev QueryCounts := FunctionStats × MemoryCounts
79+ /-- Query counts shipped back from the Rust executor. -/
80+ structure QueryCounts where
81+ functionStats : FunctionStats
82+ memoryCounts : MemoryCounts
83+ deriving Inhabited
7684
85+ /-- Raw FFI tuple shape — kept tuple-flat so the Rust side can build it
86+ without declaring matching Lean structure ctors. `execute` wraps the
87+ result in the structured `QueryCounts` immediately. -/
7788@ [extern "rs_aiur_toplevel_execute" ]
7889private opaque execute' : @& Bytecode.Toplevel →
7990 @& Bytecode.FunIdx → @& Array G → (ioData : @& Array G) →
8091 (ioMap : @& Array (Array G × IOKeyInfo)) →
81- Except String (Array G × (Array G × Array (Array G × IOKeyInfo)) × QueryCounts)
92+ Except String (Array G × (Array G × Array (Array G × IOKeyInfo))
93+ × (Array (Array (Nat × Nat × Nat × Nat)) × Array (Nat × Nat)))
8294
8395/-- Executes the bytecode function `funIdx` with the given `args` and `ioBuffer`,
8496returning the raw output of the function, the updated `IOBuffer`, and a
85- `QueryCounts` (per-function split stats + per-memory `(uniqueRows, totalHits)`
86- pairs). Returns `Except.error msg` when execution fails (e.g. `assert_eq!`
87- mismatch from a typechecker rejecting a constant), so callers can recover
88- instead of crashing. -/
97+ `QueryCounts`. Returns `Except.error msg` when execution fails (e.g.
98+ `assert_eq!` mismatch from a typechecker rejecting a constant), so callers
99+ can recover instead of crashing. -/
89100def execute (toplevel : @& Bytecode.Toplevel)
90101 (funIdx : @& Bytecode.FunIdx) (args : @& Array G) (ioBuffer : IOBuffer) :
91102 Except String (Array G × IOBuffer × QueryCounts) :=
92103 let ioData := ioBuffer.data
93104 let ioMap := ioBuffer.map
94105 match execute' toplevel funIdx args ioData ioMap.toArray with
95106 | .error e => .error e
96- | .ok (output, (ioData, ioMap), queryCounts ) =>
107+ | .ok (output, (ioData, ioMap), rawFn, rawMem ) =>
97108 let ioMap := ioMap.foldl (fun acc (k, v) => acc.insert k v) ∅
98- .ok (output, ⟨ioData, ioMap⟩, queryCounts)
109+ let functionStats : FunctionStats := rawFn.map fun perFn =>
110+ perFn.map fun quad =>
111+ { groupIdx := quad.1 , totalWidth := quad.2 .1 ,
112+ uniqueRows := quad.2 .2 .1 , totalHits := quad.2 .2 .2 }
113+ let memoryCounts : MemoryCounts := rawMem.map fun pair =>
114+ { uniqueRows := pair.1 , totalHits := pair.2 }
115+ .ok (output, ⟨ioData, ioMap⟩, { functionStats, memoryCounts })
99116
100117end Bytecode.Toplevel
101118
0 commit comments