Overview
When an editor operation modifies a roster, wham creates a brand-new WhamCompilation. All old ISymbol instances become invalid — they are bound to the old compilation. Higher layers (editor, UI) that held references to symbols or nodes from the previous compilation have no way to reconnect to their equivalents in the new compilation.
This epic introduces Roslyn-inspired mechanisms for stable symbol identity, incremental compilation, and workspace state management.
Background: Roslyn Patterns
This design is informed by analysis of Roslyn's approach to the same problem:
| Roslyn Mechanism |
Wham Equivalent |
Notes |
SymbolKey |
SymbolKey (Phase 1) |
Simpler: BattleScribe IDs provide natural keys |
CompilationTracker |
Catalogue/Roster split (Phase 2) |
Natural split: catalogues stable, roster volatile |
Solution forking |
RosterState exists |
Structural sharing via immutable source tree arrays |
TranslationAction |
IRosterOperation exists |
Already have typed operation objects |
Project deps |
Roster→Catalogue deps (Phase 2) |
Roster depends on subset of catalogues |
SemanticModel |
EffectiveEntryCache |
Per-roster cached effective entries |
SyntaxAnnotation |
Not needed |
All roster nodes have unique generated IDs |
Key Insight: All Symbols Have Unique IDs
All wham symbols — both catalogue-defined entries AND roster elements — have stable, unique IDs via IIdentifiableNode.Id:
- Catalogue entries (SelectionEntry, ForceEntry, CategoryEntry, etc.): IDs authored in BattleScribe data files. Unique within a catalogue.
- Roster elements (Force, Selection, Category in roster): IDs generated at creation time via
Guid.NewGuid() (see NodeFactory.NewId()). Each roster force/selection gets its own unique ID — even multiple selections from the same entry.
This means a single SymbolKey mechanism can handle ALL symbol types uniformly, unlike Roslyn which needs both SymbolKey (for symbols) and SyntaxAnnotation (for syntax nodes without inherent IDs).
Key Differences from Roslyn
- Natural stable IDs everywhere: BattleScribe authored IDs on catalogue entries, plus generated GUIDs on roster elements. Roslyn must synthesize identity from names/signatures.
- Natural project structure: Catalogues = referenced projects (stable), Rosters = current project (volatile). Multiple rosters share catalogues.
- No incremental parsing needed: BattleScribe XML loaded in bulk. Roster tree replaced atomically.
- Smaller scale: ~1 gamesystem + N catalogues (typically <20) + 1-few rosters.
Phases
Phase 1: SymbolKey — Cross-compilation symbol identity
Unified SymbolKey struct for all symbol types. Replaces ad-hoc ID-based lookups in editor operations.
Phase 2: Incremental Compilation — Catalogue/roster split with dependency graph
Split compilation into stable catalogue compilation + per-roster compilation. Multiple rosters share catalogue symbols.
Phase 3: Workspace Layer — Multi-roster management
WhamWorkspace managing current state, CompilationTracker per roster, document identity, change notifications.
Current Pain Points
AddRootEntryFromSymbol (RosterOperations.cs:195): "hack for referencing symbols from previous compilations, until SymbolReference is done"
AddSelectionFromLinkOp (line 179): force lookup by ID because ForceNode invalidated by prior operations
- All catalogue symbols rebuilt from scratch even when only the roster changes
- No support for multiple simultaneous rosters sharing catalogue data
Overview
When an editor operation modifies a roster, wham creates a brand-new
WhamCompilation. All oldISymbolinstances become invalid — they are bound to the old compilation. Higher layers (editor, UI) that held references to symbols or nodes from the previous compilation have no way to reconnect to their equivalents in the new compilation.This epic introduces Roslyn-inspired mechanisms for stable symbol identity, incremental compilation, and workspace state management.
Background: Roslyn Patterns
This design is informed by analysis of Roslyn's approach to the same problem:
SymbolKeySymbolKey(Phase 1)CompilationTrackerSolutionforkingRosterStateexistsTranslationActionIRosterOperationexistsProjectdepsSemanticModelSyntaxAnnotationKey Insight: All Symbols Have Unique IDs
All wham symbols — both catalogue-defined entries AND roster elements — have stable, unique IDs via
IIdentifiableNode.Id:Guid.NewGuid()(seeNodeFactory.NewId()). Each roster force/selection gets its own unique ID — even multiple selections from the same entry.This means a single
SymbolKeymechanism can handle ALL symbol types uniformly, unlike Roslyn which needs bothSymbolKey(for symbols) andSyntaxAnnotation(for syntax nodes without inherent IDs).Key Differences from Roslyn
Phases
Phase 1:
SymbolKey— Cross-compilation symbol identityUnified
SymbolKeystruct for all symbol types. Replaces ad-hoc ID-based lookups in editor operations.Phase 2: Incremental Compilation — Catalogue/roster split with dependency graph
Split compilation into stable catalogue compilation + per-roster compilation. Multiple rosters share catalogue symbols.
Phase 3: Workspace Layer — Multi-roster management
WhamWorkspacemanaging current state,CompilationTrackerper roster, document identity, change notifications.Current Pain Points
AddRootEntryFromSymbol(RosterOperations.cs:195): "hack for referencing symbols from previous compilations, until SymbolReference is done"AddSelectionFromLinkOp(line 179): force lookup by ID because ForceNode invalidated by prior operations