mirror of
https://github.com/johndoe6345789/tla_visualiser.git
synced 2026-04-24 21:55:24 +00:00
356 lines
9.3 KiB
Markdown
356 lines
9.3 KiB
Markdown
# Architecture Overview
|
|
|
|
This document describes the architecture and design of TLA+ Visualiser.
|
|
|
|
## High-Level Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ QML UI Layer │
|
|
│ (ImportView, GraphView, TraceView, InvariantView) │
|
|
└────────────────────┬────────────────────────────────────┘
|
|
│ Qt Signals/Slots
|
|
┌────────────────────▼────────────────────────────────────┐
|
|
│ Qt Models (QAbstractListModel) │
|
|
│ StateGraphModel TraceViewerModel │
|
|
└──────────┬──────────────────────┬───────────────────────┘
|
|
│ │
|
|
┌──────────▼──────────┐ ┌────────▼─────────────────────┐
|
|
│ GitHubImporter │ │ TLCRunner │
|
|
│ - URL parsing │ │ - Process management │
|
|
│ - HTTP requests │ │ - Output parsing │
|
|
│ - Local caching │ │ - Result serialization │
|
|
└─────────────────────┘ └──────────────────────────────┘
|
|
```
|
|
|
|
## Component Details
|
|
|
|
### 1. UI Layer (QML)
|
|
|
|
**Purpose**: Provides the user interface using Qt Quick/QML.
|
|
|
|
**Components**:
|
|
- `main.qml`: Application window, menu bar, tab navigation
|
|
- `ImportView.qml`: GitHub URL input and spec preview
|
|
- `GraphView.qml`: State/transition graph visualization
|
|
- `TraceView.qml`: Step-by-step trace inspection
|
|
- `InvariantView.qml`: Invariant status dashboard
|
|
|
|
**Communication**: Uses Qt's property binding and signal/slot mechanism to interact with C++ models.
|
|
|
|
### 2. Model Layer (Qt Models)
|
|
|
|
#### StateGraphModel
|
|
**Responsibility**: Provides data for state graph visualization.
|
|
|
|
**Key Methods**:
|
|
- `loadFromResults()`: Populate from TLC results
|
|
- `getTransitions()`: Return transition edges
|
|
- `getStateDetails()`: Get details for specific state
|
|
|
|
**Data**:
|
|
- States with positions (x, y coordinates)
|
|
- Transitions (edges between states)
|
|
- Layout calculated using circular algorithm
|
|
|
|
#### TraceViewerModel
|
|
**Responsibility**: Provides data for trace/counterexample viewing.
|
|
|
|
**Key Methods**:
|
|
- `loadTrace()`: Load a counterexample trace
|
|
- `exportToJson()`: Export trace as JSON
|
|
- `exportToMarkdown()`: Export trace as Markdown
|
|
|
|
**Data**:
|
|
- Sequence of trace steps
|
|
- Current step index
|
|
- Variable values at each step
|
|
|
|
### 3. Business Logic Layer
|
|
|
|
#### GitHubImporter
|
|
**Responsibility**: Fetch TLA+ specs from GitHub.
|
|
|
|
**Features**:
|
|
- **URL Parsing**: Regex-based parsing of GitHub URLs
|
|
- File URLs: `github.com/owner/repo/blob/branch/path`
|
|
- Raw URLs: `raw.githubusercontent.com/owner/repo/branch/path`
|
|
- Repo URLs: `github.com/owner/repo`
|
|
|
|
- **HTTP Communication**: Uses libcurl for HTTP requests
|
|
- Follows redirects
|
|
- Sets User-Agent header
|
|
- Error handling
|
|
|
|
- **Local Caching**: Saves fetched content to temp directory
|
|
- Cache key: `owner_repo_branch_filepath`
|
|
- Automatic cache lookup before fetching
|
|
|
|
**Design Pattern**: PIMPL (Pointer to Implementation)
|
|
- Public interface in header
|
|
- Private implementation in .cpp
|
|
- Hides libcurl details from API users
|
|
|
|
#### TLCRunner
|
|
**Responsibility**: Execute TLC model checker and parse results.
|
|
|
|
**Features**:
|
|
- **Process Management**: Runs TLC as external Java process
|
|
- Async execution in separate thread
|
|
- Cancellation support
|
|
- Status callbacks
|
|
|
|
- **Output Parsing**: Parses TLC text output
|
|
- State count extraction
|
|
- Error message collection
|
|
- Timing information
|
|
|
|
- **Result Persistence**: Save/load results
|
|
- Text-based format (upgradable to JSON)
|
|
- Deterministic runs
|
|
|
|
**States**:
|
|
- NotStarted
|
|
- Running
|
|
- Completed
|
|
- Failed
|
|
- Cancelled
|
|
|
|
**Design Pattern**: PIMPL + Observer (callbacks)
|
|
|
|
## Data Flow
|
|
|
|
### Import Flow
|
|
```
|
|
User enters URL
|
|
↓
|
|
ImportView captures input
|
|
↓
|
|
GitHubImporter.parseUrl()
|
|
↓
|
|
GitHubImporter.fetchFile()
|
|
├─→ Check cache
|
|
└─→ HTTP request (libcurl)
|
|
↓
|
|
Content displayed in ImportView
|
|
```
|
|
|
|
### Model Check Flow
|
|
```
|
|
User clicks "Run Model Checker"
|
|
↓
|
|
TLCRunner.startModelCheck()
|
|
↓
|
|
Spawn Java process (TLC)
|
|
↓
|
|
Parse output in background thread
|
|
↓
|
|
Update status via callback
|
|
↓
|
|
TLCRunner.getResults()
|
|
↓
|
|
StateGraphModel.loadFromResults()
|
|
TraceViewerModel.loadTrace()
|
|
↓
|
|
UI updates via Qt property bindings
|
|
```
|
|
|
|
### Visualization Flow
|
|
```
|
|
User switches to Graph View
|
|
↓
|
|
StateGraphModel provides data
|
|
├─→ Node positions (calculated)
|
|
├─→ Edge list
|
|
└─→ State details
|
|
↓
|
|
QML Canvas or GraphicsView renders
|
|
↓
|
|
User clicks node
|
|
↓
|
|
Model provides details for selected node
|
|
```
|
|
|
|
## Design Patterns
|
|
|
|
### PIMPL (Pointer to Implementation)
|
|
Used in: `GitHubImporter`, `TLCRunner`, `StateGraphModel`, `TraceViewerModel`
|
|
|
|
**Benefits**:
|
|
- Binary compatibility (ABI stability)
|
|
- Faster compilation (hidden dependencies)
|
|
- Implementation flexibility
|
|
|
|
**Structure**:
|
|
```cpp
|
|
class MyClass {
|
|
public:
|
|
MyClass();
|
|
~MyClass();
|
|
void publicMethod();
|
|
private:
|
|
class Impl;
|
|
std::unique_ptr<Impl> pImpl;
|
|
};
|
|
```
|
|
|
|
### Observer Pattern
|
|
Used in: `TLCRunner` callbacks
|
|
|
|
**Benefits**:
|
|
- Async notification
|
|
- Decoupling
|
|
|
|
**Usage**:
|
|
```cpp
|
|
runner.setStatusCallback([](Status s) {
|
|
// Handle status change
|
|
});
|
|
```
|
|
|
|
### Model-View (Qt)
|
|
Used throughout for UI
|
|
|
|
**Benefits**:
|
|
- Separation of concerns
|
|
- Automatic updates
|
|
- Testable models
|
|
|
|
### Factory Pattern (Future)
|
|
Could be used for:
|
|
- Different graph layout algorithms
|
|
- Export format handlers
|
|
|
|
## Threading Model
|
|
|
|
### Main Thread
|
|
- Qt event loop
|
|
- UI updates
|
|
- User interaction
|
|
- Model data access
|
|
|
|
### Background Threads
|
|
- TLC execution (via `std::thread`)
|
|
- HTTP requests (via libcurl)
|
|
|
|
**Synchronization**: Qt signals/slots (thread-safe when queued)
|
|
|
|
## Memory Management
|
|
|
|
- **Smart Pointers**: `std::unique_ptr` for PIMPL idiom
|
|
- **Qt Parent-Child**: QObjects use Qt's parent-child ownership
|
|
- **RAII**: Resources cleaned up in destructors
|
|
- **No Manual new/delete**: Prefer stack allocation or smart pointers
|
|
|
|
## Error Handling
|
|
|
|
### Current Strategy
|
|
- Return values (bool for success/failure)
|
|
- Empty returns for errors (empty string, empty vector)
|
|
- Error messages stored in result structures
|
|
|
|
### Future Improvements
|
|
- Exception-based error handling
|
|
- Error codes enumeration
|
|
- Detailed error context
|
|
|
|
## Dependencies
|
|
|
|
### External Libraries
|
|
- **Qt 6**: UI framework, models, networking
|
|
- **libcurl**: HTTP requests
|
|
- **C++ Standard Library**: Containers, threading, filesystem
|
|
|
|
### Dependency Management
|
|
- **Conan**: Package manager for libcurl
|
|
- **CMake**: Build system integration
|
|
- **Find Modules**: Qt6 via CMake's built-in finder
|
|
|
|
## Extensibility Points
|
|
|
|
### Adding New Visualizations
|
|
1. Create new QML view (e.g., `TimelineView.qml`)
|
|
2. Create corresponding Qt model (e.g., `TimelineModel`)
|
|
3. Add tab in `main.qml`
|
|
4. Load data from `TLCRunner::RunResults`
|
|
|
|
### Adding New Import Sources
|
|
1. Create new importer class (e.g., `GitLabImporter`)
|
|
2. Implement common interface
|
|
3. Add UI option to select source
|
|
4. Integrate in `ImportView`
|
|
|
|
### Adding New Export Formats
|
|
1. Add export method to model (e.g., `exportToXML()`)
|
|
2. Add UI button/menu item
|
|
3. Implement serialization logic
|
|
|
|
## Testing Strategy
|
|
|
|
### Unit Tests
|
|
- **GitHubImporter**: URL parsing, cache operations
|
|
- **TLCRunner**: Status management, result saving
|
|
- **Models**: Data loading, transformations
|
|
|
|
### Integration Tests (Future)
|
|
- End-to-end import flow
|
|
- TLC execution with sample specs
|
|
- Export functionality
|
|
|
|
### UI Tests (Future)
|
|
- QML test framework
|
|
- Automated UI interaction
|
|
|
|
## Performance Considerations
|
|
|
|
### Current Optimizations
|
|
- Circular layout O(n) complexity
|
|
- Local caching to avoid redundant downloads
|
|
- Async TLC execution
|
|
|
|
### Future Optimizations
|
|
- Lazy loading for large graphs
|
|
- Level-of-detail rendering
|
|
- Progressive result display
|
|
- Worker threads for layout calculation
|
|
|
|
## Security Considerations
|
|
|
|
### Current Measures
|
|
- No credential storage
|
|
- Read-only spec access
|
|
- Local cache in temp directory
|
|
|
|
### Future Improvements
|
|
- GitHub token authentication (optional)
|
|
- HTTPS certificate validation
|
|
- Input sanitization for TLC invocation
|
|
- Sandboxed TLC execution
|
|
|
|
## Build System
|
|
|
|
### CMake Configuration
|
|
- Minimum version: 3.22
|
|
- C++20 standard requirement
|
|
- Qt6 modules: Core, Gui, Quick, Widgets
|
|
- Conan integration via toolchain file
|
|
|
|
### Platform Support
|
|
- **Linux**: Native builds, ARM64 via QEMU
|
|
- **macOS**: Native builds (x86_64, arm64)
|
|
- **Windows**: MSVC and MinGW support
|
|
|
|
### CI/CD
|
|
- GitHub Actions workflows
|
|
- Multi-platform builds
|
|
- Automated testing
|
|
- Artifact uploads
|
|
|
|
## Future Architecture Improvements
|
|
|
|
1. **Plugin System**: Allow third-party visualizations
|
|
2. **Async I/O**: libuv or Boost.Asio for better performance
|
|
3. **Database**: SQLite for result persistence
|
|
4. **Language Server**: TLA+ LSP integration
|
|
5. **Web Backend**: Optional web UI via REST API
|