Open
Description
Goals
Enrich exploration, visualization, and interaction with results in an object trace. Add support for domain-specific representations.
Features
- Dynamic fraying (could we please find a good term for this?): If the representation causes a frayout (maybe triggered through the user), insert a (differently layouted) context slice tree for it in the history explorer under the original leaf.
- Blame: If the user selects an aspect from the representation, highlight all context slices in the history explorer that caused a change in this aspect.
- for later: multiple blames with different colors? e.g., hover vs select
- maybe generic version: filter times from memory slice instead of automatic coalescion of memory slice (e.g., to find all context tree slices where value is larger than x)
- Aspect-centric stepping: Similar to blame, the user can select an aspect from the representation and step to its next or previous change.
- Time-based stepping: For global representations that display the entire object trace (not just the current selection), the user can select another context slice from the representation to step to it.
Use cases
- Explore sorting algorithm: Display all items of the collections in a list widget (instead of a textual representation).
- Dynamically explore the genesis of a data structure: Expand relevant nodes in an object-explorer-like representation of the data structure. Blame of changes to selected variable.
- Visualize and explore regex matching: Visualization of matcher graph and current thread position. Blame of activations of selected link. Display matched string, currently consumed substring, and all currently captured subexpressions, again with blame.
- Smalltalk debugger: Context stack, source code, next expression (pc), variables. Could we reuse the normal debugger class here? Additional features: context tree, stepping buttons.
Possible representations
- generic-purpose:
- default (the current "details" view):
- automatic choice of representation (string, text, form, maybe others)
- object explorer
- based on
explorerContents
- frayouts for value, children, and icons (?) of each item
- blame/aspect-centric stepping for variables
- should there be support for custom fields? multiple contents sources to choose from?
- based on
- pluggable representation?
- vague idea: something where users can define different aspects/expressions, plug them together, and choose between custom representations (e.g., default, object explorer, etc.) to create some kind of dashboard?
- default (the current "details" view):
- domain-specific:
- regex matcher:
- based on
RxvMorph
; uses both matcher and context
- based on
- Smalltalk debugger:
- based on
TDBHistoryExplorer class>>#exampleSimulator
, but may just use context
- based on
- charts for numeric values:
- display all values in a chart (line chart, bar chart, autc.) together with context slice on x-axis
- blame/aspect-centric stepping for y-axis
- time-based stepping for x-axis
- regex matcher:
Forces
- Keep the interface for custom representations as minimal and decoupled from history explorer as possible. In particular, representations should not be forced to deal with proxy details.
- Sufficient performance. Running too much logic inside the range retracer degrades performance significantly (e.g., scaling a form or converting it to text).
Representation protocol
Representation:
- set history explorer
- toolbuilding (
buildWith:
) - update selection from he:
- set selected object and context (both possibly passed as range proxies) and also context tree slice for global representations
- representation might register external frayout on this
- any representation state (e.g., collapsed/expanded nodes) should be stored in a dictionary per context tree slice, when context tree slice is changed, state should be tried to update based on previous selection
- set selected fray-object and fray-context (both possibly passed as range proxies from pre-aggregated view data) and also context tree slice (from frayout) for global representations
- representation should NOT encounter further frayouts now!
- set selected fray-object and fray-context (both possibly passed as range proxies from pre-aggregated view data) and also context tree slice (from frayout) for global representations (from inner (non-leaf) context tree slice of frayout/pre-aggregated view data)
- representation might display either nothing or inlined frayouts, but not register external frayouts
- set selected object and context (both possibly passed as range proxies) and also context tree slice (from original object trace) for global representations (from inner (non-leaf) context tree slice)
- same as 1., can register external frayouts
- special notes for object explorer representation:
- compute pre-aggregated view data eagerly, maintain for current context tree slice selection in representation, maintain expanded paths
- when new children are requested, update expanded paths and update pre-aggregated view data (can we only recompute part?), then answer inlined frayout or nothing
- because each expansion would trigger multiple children requests, it would be helpful to be informed by the view about the expansion itself -> if a hasChildrenSelector is implemented, this should suffice for differentiation
- when child is collapsed, update expanded paths and pre-aggregated view data again
- set selected object and context (both possibly passed as range proxies) and also context tree slice for global representations
- indicate whether inner nodes are supported
- if not, history explorer could send last leaf instead
- TODO or should the representation handle this internally?
- get entire memory slice + context slice from history explorer
- class-side: provide representation services (check whether appropriate for a given object trace, provide label and constructor)
History explorer:
- update frayout (register + unregister?) (causes internal construction and display of nested context tree slice, sends back fray selection to representation)
- formally: a memory slice of pre-aggregated view data for a context tree slice (leaf or inner node of original object trace)
- if referenced context tree slice is an inner node, split up frayout to the different leafs
- representation may send new frayout to he whenever an inner node is selected (?), so only apply update if really new (?)
- if we support multiple frayouts, there is only update, which replaces any previous frayout for the same time range. nested context tree slices would then be stored in a list.
- step to context slice
- set/unset blame expression
- blame expression is evaluated against unioned memory slice including all frayouts; result is maybe coalesced; time indices in result are used for highlighting context tree slice leaves
- aspect-centric stepping: step to next/previous change of expression
Open questions
archived:
- what is displayed when an inner node (non-leaf) is selected? -> send partial frayout to representation, which can display nothing or inlined frayouts
- when do we actually want to combine both a variable expression and a custom representation? is this overkill/confusing and should be separated? -> scenario: algorithm copies data structure (mix of mutable and immutable ops). if possible, try to honor that.
- display frayouts in he for all objects in object trace or just for currently selected? -> more complicated, but potentially more helpful. idea: whenever frayouts anywhere might change (i.e., because state (such as collapsed/expanded) in representation is changed), send all objects from object trace to representation after each other to trigger frayout updates. frayouts are not unregistered but just replaced. potentially performance-critical! keep this optional for now.
- how does blaming/aspect-centric stepping across different frayouts look like and work? -> evaluate blame expression not against memory slice of current frayout but against global memory slice with all frayout memory slices merged in
- what concretely is selected when a frayout occurs? -> if components have state (e.g., expanded/collapsed in explorer representation), they should store them in a dictionary for the different objects and try to propagate updates to all states. in general, context tree slice selection is not changed when frayout occurs, however we could consider if a representation indicates that it does not support inlined frayouts to directly jump to the first leaf.
- how does passed context look like (range proxy based on multiple values)? -> think we already use this for spawn, but maybe extract this concept. this is impractical without coalescion!
- how can the representation control frayouts (e.g., catch frayouts within a list item's string representation but propagate frayouts for different list items with different identity, and also propagate frayouts for different list sizes) -> two-pass: 1. send message to force external frayouts, 2. transform list to string representation and catch frayouts
- how to deal with collapsed nodes inside fray tree? -> last leaf like in rest of he
- how does blame work? -> we have a general issue/unclarity with identity of results from range proxy (History Explorer Coalescion #94). simple solution: convert each blame expression result to primitive representation such as string.
- how does aspect-based stepping work? -> based on memory slice for blame. if we want to support "step over" here, need to manually compare with context tree slice
NEXT STEPS:
- decide vocabulary
- build minimal implementation for list representation