Skip to content

Commit 8afcec9

Browse files
authored
Merge branch 'probe-III' into sorted-insertion
2 parents 24a80ef + 8905741 commit 8afcec9

File tree

25 files changed

+1424
-91
lines changed

25 files changed

+1424
-91
lines changed
Lines changed: 357 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,357 @@
1+
# Closure Cursor Bar - Deferred Ideas
2+
3+
## Collapsing Recursive Runs
4+
5+
**Concept:** When you have a run of recursive function applications (e.g., `map` called repeatedly), collapse them into something like `map ↻5` with a count.
6+
7+
**Considerations:**
8+
- For built-in HOFs (map, fold, filter): Makes more sense since intermediate calls are structurally identical
9+
- For general recursion: Trickier - different recursive calls might represent different states/arguments
10+
- UX question: What does clicking a collapsed run do? Which call do you jump to?
11+
- Name click → outer call site (the actual calling of the function, not inner recursive calls)
12+
- Number/arrow click → expand to show all?
13+
- Could be a toggleable option, perhaps off by default
14+
- The inner recursive calls don't correspond to the same application site
15+
16+
**Status:** Holding off. Current display with blue color + 0.7 opacity already visually subordinates ghost entries. Revisit if deep recursive stacks prove cluttered in practice.
17+
18+
---
19+
20+
## Ghost Entry Toggle
21+
22+
**Concept:** Double chevron (`❯❯`) before first ghost entry that toggles visibility of ghost entries.
23+
24+
**What we tried:**
25+
- Double chevron replacing the separator before first ghost entry
26+
- Clicking it would: jump to location + set index + toggle visibility
27+
28+
**Why we removed it:**
29+
- Conflicting behaviors on single click (navigate vs toggle)
30+
- Modifier key (shift+click) felt awkward
31+
- Separate toggle button added clutter
32+
33+
**Current state:** Double chevron visual indicator disabled. Ghost entries always shown with 0.7 opacity + blue color coding.
34+
35+
**Status:** Removed for now. Could revisit with a cleaner interaction model if needed.
36+
37+
---
38+
39+
## Indicated Entry Highlighting (Red Outline)
40+
41+
**Concept:** Show a red outline/border on a breadcrumb entry when the editor cursor is "related" to that function call - similar to how indicated samples get a red border.
42+
43+
### Option 1: Cursor on the app expression
44+
- Check if `indicated_id == app_id`
45+
- **Difficulty: Easy** - we already have `app_id` for each entry, just need to pass `indicated_id` to the view function
46+
47+
### Option 2: Cursor on the function name/variable
48+
- Check if `indicated_id == fn_id` (the ID of the function expression in the app)
49+
- **Difficulty: Easy** - we already extract `fn_id` in `get_fn_info`
50+
51+
### Option 3: Cursor inside the function body
52+
- Get the binding site of the function via `Info.get_binding_site`
53+
- Check if `indicated_id` is a descendant/contained within that body
54+
- **Difficulty: Medium** - needs parent traversal or containment check
55+
- Note: There may already be helpers for this - auto-probe mechanism likely uses something similar. Check `ProbePerform.re` or related files for existing "is inside function" helpers. May want to extract to a shared helper location.
56+
57+
### Option 4: Cursor inside lexical extent of the let binding
58+
- Similar to #3 but includes the pattern side too
59+
- **Difficulty: Medium** - same containment check approach
60+
61+
### Implementation Notes:
62+
- `Indicated.piece(zipper)` or similar gives the indicated ID
63+
- For #3-4, look for existing helpers in auto-probe code before writing new ones
64+
- Could start with #1 (easiest) and expand later
65+
66+
**Status:** Option 1 implemented. Options 2-4 deferred.
67+
68+
---
69+
70+
## Separator Click / Sample Indication Sync (TODO - Investigate)
71+
72+
**Observed issue:** When clicking a separator in the closure cursor bar, the breadcrumb entry gets the red "indicated" outline (because the syntax cursor moves to the app_id), but the corresponding **sample** in the probe doesn't get indicated.
73+
74+
**Possible cause:** Sample indication is tied to `indicated_call` in `sample_cursor`, which only gets set when clicking directly on a sample (via `Capture` action). Clicking the separator only calls `SetIndex` + `jump_to` - it doesn't set `indicated_call`.
75+
76+
**Possible off-by-one aspect:** The sample cursor index might be at a different depth than expected, causing the "wrong" sample to appear indicated (or none at all).
77+
78+
**To investigate:**
79+
- How does `indicated_call` interact with sample display?
80+
- Should separator clicks set `indicated_call`?
81+
- Is there an index mismatch between breadcrumb position and sample filtering?
82+
83+
**Status:** Needs investigation. Noted late at night when too tired to fully diagnose.
84+
85+
---
86+
87+
## Dropdown Menus Showing Branching Paths
88+
89+
**Concept:** Dropdown menus on breadcrumb entries that show different call paths from the sample data.
90+
91+
### Example
92+
```
93+
let double = fun x -> x * 2
94+
let process = fun y -> double(y) + double(y + 1)
95+
process(5)
96+
```
97+
98+
Call stacks from samples inside `double`:
99+
- `[process_app, double_app_1]` → first call, `double(5)`
100+
- `[process_app, double_app_2]` → second call, `double(6)`
101+
102+
Dropdown on `double` entry could show:
103+
```
104+
┌─────────────┐
105+
│ double(5) │ ← from first call site
106+
│ double(6) │ ← from second call site
107+
└─────────────┘
108+
```
109+
110+
### For map/fold iterations
111+
```
112+
map(fun x -> x + 1, [1, 2, 3])
113+
```
114+
115+
Dropdown could show iteration index or input value:
116+
```
117+
┌───────────┐
118+
│ map @ [1] │
119+
│ map @ [2] │
120+
│ map @ [3] │
121+
└───────────┘
122+
```
123+
124+
### Tree Structure Observation
125+
All sample call stacks form a tree - they share common prefixes. The closure cursor bar shows one **path** through this tree. Dropdowns would show **siblings** at each node.
126+
127+
### Data Source
128+
- Use all collected samples from evaluation
129+
- Each sample has call_stack, step_start, step_end (temporal ordering)
130+
- The step ranges give partial order on expression evaluation durations
131+
132+
**Limitations:**
133+
- Works well when there are distinct, meaningful branches
134+
- For deep recursion with many similar calls, could get unwieldy
135+
- Best for: small numbers of distinct call sites, built-in HOFs where iteration context is meaningful
136+
137+
**Status:** Deferred. Explore if dropdown navigation proves useful for debugging workflows.
138+
139+
---
140+
141+
## Investigation Breadcrumbs / Backtracking Debugging
142+
143+
**Concept:** A debugging history system separate from the call stack, allowing you to mark "investigation points" and backtrack when pursuing one path doesn't pan out.
144+
145+
### Motivation
146+
When debugging, you often:
147+
1. Trace down through function calls following a wrong value
148+
2. Find an expression that's giving the wrong result
149+
3. That expression might have multiple variable references - each potentially the bug source
150+
4. You want to pursue one, and if it doesn't pan out, backtrack and try another
151+
152+
### Example
153+
```
154+
let a = 5
155+
let b = 10
156+
let c = a + b // result is 15, but expected 20
157+
```
158+
159+
Debugging flow:
160+
1. Mark `a + b` as an "investigation point"
161+
2. Pursue `a` → trace back, see it's 5, looks fine
162+
3. **Backtrack** to investigation point
163+
4. Pursue `b` → trace back, find the bug
164+
165+
### Conceptual Model
166+
An "investigation stack" separate from call stack:
167+
```
168+
Investigation Stack:
169+
├─ [1] a + b at line 3 (problem is in dynamic extent of this)
170+
│ ├─ [1.1] pursuing `a` → checked, looks fine
171+
│ └─ [1.2] pursuing `b` → (current investigation)
172+
```
173+
174+
### Key Distinction from Current Pin
175+
- Pin filters which samples are shown
176+
- Investigation breadcrumbs track **your debugging path** (where you've looked), not just the **program's call path** (what executed)
177+
178+
### Possible UI
179+
- Mark expressions as "investigation points" (separate from pin)
180+
- Small panel or dropdown showing investigation history
181+
- Keyboard shortcuts: mark point, go back, go forward
182+
- Closure cursor bar indicator if you're "inside" an investigation
183+
184+
### Related Concept: Multiple Pins
185+
Could also be implemented as multiple pins with a stack/tree structure, rather than just one pin.
186+
187+
**Status:** Deferred. This is a more general debugging workflow enhancement. Could be valuable for complex debugging scenarios.
188+
189+
---
190+
191+
## Keyboard Navigation
192+
193+
**Concept:** Navigate the closure cursor bar with keyboard.
194+
195+
### MVP (Implemented)
196+
- Left/Right arrow keys to move between breadcrumb entries
197+
- Enter to jump to the current entry's definition (then refocuses main editor)
198+
199+
### Focus Shortcut (TODO)
200+
Need a keyboard shortcut to focus the closure cursor bar from the main editor.
201+
202+
**Candidate shortcuts:**
203+
- `Ctrl+;` - ergonomic, usually unbound
204+
- `Ctrl+Shift+K` - mnemonic for "call stacK"
205+
- `Ctrl+Shift+D` - mnemonic for "Dynamic cursor"
206+
207+
**TODO:** Check with team on preferred shortcut to avoid conflicts with existing bindings.
208+
209+
### Extension: Dropdown Navigation
210+
- Down arrow opens a dropdown showing function applications within the current function body
211+
- Could show applications that are lexically inside the function definition
212+
- Selecting one would jump to it (and possibly add a probe if needed)
213+
- This would allow keyboard-based navigation through the entire call structure
214+
215+
### Data Source Questions
216+
- Should dropdowns be populated from dynamics (what actually executed) or lexically (what apps exist in the function body)?
217+
- Lexical: Always shows all possible calls, even if not executed this run
218+
- Dynamic: Only shows calls that actually happened, with sample data
219+
- Could be a combination: lexical structure, annotated with dynamic info
220+
221+
**Status:** MVP implemented. Focus shortcut pending. Dropdown extension deferred.
222+
223+
---
224+
225+
## Bidirectional Hover Highlighting
226+
227+
**Concept:** Highlight matching elements when hovering.
228+
229+
### Breadcrumb → Sample
230+
When hovering a breadcrumb entry, highlight the corresponding sample(s) in probes.
231+
232+
### Sample → Breadcrumb
233+
When hovering a sample in a probe, highlight the matching breadcrumb entry.
234+
235+
### Implementation Thoughts
236+
- Would likely need a `hover_cursor` field separate from the committed `sample_cursor`
237+
- Both probes and closure cursor bar would check this for highlighting
238+
- Similar infrastructure to indicated highlighting, but triggered by hover instead of syntax cursor
239+
240+
**Status:** Deferred. Useful for understanding correspondence between bar and samples.
241+
242+
---
243+
244+
## Argument Values in Tooltips
245+
246+
**Concept:** Show argument values in breadcrumb tooltips, e.g., `map([1,2,3])` instead of just `map`.
247+
248+
### Implementation Challenges
249+
- Need to probe the argument expressions to capture their values
250+
- Would require adding app argument IDs to sample targets before evaluation
251+
- Closure cursor bar currently only receives statics info, would need dynamics too
252+
- Need to fish out the argument values from samples and format them
253+
254+
### Alternative: Lighter Version
255+
- Just show the argument expressions (syntax), not their values
256+
- This is available from statics without additional probing
257+
258+
**Status:** Deferred. Requires infrastructure changes. Consider lighter syntax-only version first.
259+
260+
---
261+
262+
## Copy Call Stack
263+
264+
**Concept:** Button to copy the current call stack for debugging/sharing.
265+
266+
### Possible Formats
267+
- Human-readable: `λ > map > filter > f`
268+
- With locations: `λ > map (line 5) > filter (line 12) > f (line 3)`
269+
- JSON for tooling integration
270+
271+
**Status:** Deferred. Low priority but potentially useful for bug reports.
272+
273+
---
274+
275+
## Multiple Sample Selection
276+
277+
**Concept:** Allow selecting multiple samples for comparison/analysis.
278+
279+
### Use Cases
280+
- Compare two execution paths: "Why did `process(5)` work but `process(6)` fail?"
281+
- Call stack diff: highlight where two samples' call stacks diverge
282+
- Side-by-side value comparison
283+
284+
### Connection to Investigation Breadcrumbs
285+
- Investigation breadcrumbs track exploration history (where you've looked)
286+
- Multiple selection tracks comparison targets (what you're analyzing)
287+
- Could potentially unify: investigation points become selectable samples
288+
289+
**Status:** Deferred. Interesting direction but adds complexity. Revisit when single-cursor workflows feel limiting.
290+
291+
---
292+
293+
## Time Travel Slider
294+
295+
**Concept:** Scrub through execution using step_start/step_end data.
296+
297+
### How It Would Work
298+
- Slider representing evaluation steps
299+
- As you scrub, highlight samples whose step ranges contain the current step
300+
- Shows "program state at step N"
301+
302+
### Limitations
303+
- With probe_all: many samples, rich scrubbing experience
304+
- Without probe_all: limited to collected samples only
305+
- May need UI to indicate "no data at this step"
306+
307+
**Status:** Deferred. Interesting but depends on probe density.
308+
309+
---
310+
311+
## Evaluation Context Stepping (Exploratory)
312+
313+
**Concept:** Capture evaluation context within function calls, enabling finer-grained stepping.
314+
315+
### Current State
316+
Call stack entries represent function application boundaries. Within a function body, we don't track intermediate evaluation steps in the cursor.
317+
318+
### Possible Extension
319+
- Capture evaluation context frames (what's being evaluated within a function)
320+
- Alternating sequence: call stack entry → eval context → call stack entry → ...
321+
- Would allow stepping through entire program at expression granularity
322+
323+
### Open Questions
324+
- What exactly constitutes an "evaluation context frame"?
325+
- How to represent in UI without overwhelming?
326+
- Relationship to step_start/step_end data we already have?
327+
328+
**Status:** Very exploratory. Needs more thought on what this would look like concretely.
329+
330+
---
331+
332+
## Pin from Dynamic Cursor UI
333+
334+
**Concept:** Allow pinning directly from the closure cursor bar, not just from sample dropdowns.
335+
336+
### Possible Affordances
337+
- Right-click or long-press on breadcrumb entry shows context menu with "Pin here"
338+
- Small pin icon appears on hover (like current unpin icon, but for pinning)
339+
- Clicking would pin the call stack up to and including that entry
340+
341+
### Could We Show Full Sample Context Menu?
342+
343+
Analysis of what we'd need:
344+
345+
| Feature | Required Data | Currently Available? |
346+
|---------|--------------|---------------------|
347+
| Pin action | `app_id`, call stack | ✅ Yes - construct from `sample_cursor.call_stack` trimmed to entry index |
348+
| Step Into | Full `Sample.t` | ❌ No - needs dynamics passed in |
349+
| Environment | `sample.env`, `view_seg`, `utility` | ❌ No - needs dynamics + rendering utilities |
350+
351+
**Current ClosureCursorBar inputs:** `globals`, `refractors` (has `sample_cursor`), `info_map` (statics only)
352+
353+
**What's missing:** `Dynamics.Info.t`, samples list, `view_seg`/`utility`
354+
355+
**Verdict:** Simplified context menu with just Pin is doable now. Full menu (Step Into + Environment) requires threading dynamics through.
356+
357+
**Status:** Deferred. Pin-only version could be quick; full menu needs more plumbing.

0 commit comments

Comments
 (0)