From 6594e22318f5d94433f6dd3eec39c6e555337f00 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sat, 6 Sep 2025 18:52:19 +0800 Subject: [PATCH 01/12] Add comprehensive swift-docc documentation and architecture guide - Update README.md with detailed architecture explanation covering Attribute, Graph, and Runtime components - Create swift-docc documentation catalog with main module documentation - Add in-depth Architecture.md article explaining the three-layer system - Document key public APIs including: * Attribute struct with property wrapper documentation * Rule protocol for computed attributes * Metadata extensions for runtime type introspection - Reference wickwirew/Runtime repo for Swift runtime techniques - Include code examples and usage patterns throughout documentation --- README.md | 29 ++++ .../Attribute/Attribute/Attribute.swift | 102 +++++++++++ .../Attribute/Rule/Rule.swift | 61 +++++++ .../OpenAttributeGraph.docc/Architecture.md | 164 ++++++++++++++++++ .../OpenAttributeGraph.md | 59 +++++++ .../OpenAttributeGraph/Runtime/Metadata.swift | 20 +++ 6 files changed, 435 insertions(+) create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Architecture.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md diff --git a/README.md b/README.md index a49e0184..ebb8b59d 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,35 @@ AttributeGraph is a high performance computing engine written in C++ and Swift. And it powers the underlying computing and diffing of SwiftUI. +## Architecture + +OpenAttributeGraph consists of three main components: + +### Attribute Part +The **Attribute** system provides a reactive property wrapper that automatically tracks dependencies and manages value updates. Key features include: +- `Attribute` - A property wrapper for reactive values with automatic dependency tracking +- `AnyAttribute` - Type-erased attribute for runtime flexibility +- **Rules** - Transform attributes through `Rule` and `StatefulRule` protocols +- **Weak/Optional** - Support for optional and weak attribute references +- **Body system** - Efficient value computation and caching mechanisms + +### Graph Part +The **Graph** manages the dependency network and orchestrates updates across attributes. Core functionality includes: +- `Graph` - Central coordinator for attribute relationships and update cycles +- `Subgraph` - Scoped computation contexts for isolated attribute groups +- **Invalidation tracking** - Efficient change propagation through the dependency graph +- **Update scheduling** - Optimized batch processing of attribute changes +- **Profiling support** - Performance monitoring and debugging capabilities + +### Runtime Part +The **Runtime** provides low-level type introspection and memory management utilities. This includes: +- `Metadata` - Swift runtime type information and reflection capabilities +- **Type comparison** - Efficient value equality checking across different types +- **Memory layout** - Safe pointer manipulation and offset calculations +- **Tuple handling** - Runtime support for tuple types and field access + +> **Note**: The Runtime part leverages techniques similar to those found in [wickwirew/Runtime](https://github.com/wickwirew/Runtime) for Swift runtime introspection. + | **CI Status** | |---| |[![Compatibility tests](https://github.com/OpenSwiftUIProject/OpenAttributeGraph/actions/workflows/compatibility_tests.yml/badge.svg)](https://github.com/OpenSwiftUIProject/OpenAttributeGraph/actions/workflows/compatibility_tests.yml)| diff --git a/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift b/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift index b097ffc3..d0c1af7f 100644 --- a/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift +++ b/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift @@ -1,5 +1,67 @@ public import OpenAttributeGraphCxx +/// A reactive property wrapper that automatically tracks dependencies and manages value updates. +/// +/// `Attribute` is the core building block of the OpenAttributeGraph reactive system. When you wrap a property +/// with `@Attribute`, it becomes reactive and can automatically track dependencies and propagate changes. +/// +/// ```swift +/// @Attribute var count: Int = 0 +/// @Attribute var doubledCount: Int = count * 2 +/// +/// count = 5 // doubledCount automatically becomes 10 +/// ``` +/// +/// ## Key Features +/// +/// - **Automatic dependency tracking**: Attributes automatically discover their dependencies +/// - **Efficient updates**: Only affected attributes are recomputed when changes occur +/// - **Type safety**: Full Swift type safety with compile-time checking +/// - **Dynamic member lookup**: Access nested properties as reactive attributes +/// - **Property wrapper syntax**: Clean, declarative syntax using `@Attribute` +/// +/// ## Property Wrapper Usage +/// +/// Use `@Attribute` to make any Swift value reactive: +/// +/// ```swift +/// struct CounterView { +/// @Attribute var count: Int = 0 +/// +/// var body: some View { +/// Button("Count: \(count)") { +/// count += 1 +/// } +/// } +/// } +/// ``` +/// +/// ## Dynamic Member Lookup +/// +/// Access nested properties as separate attributes: +/// +/// ```swift +/// @Attribute var person: Person = Person(name: "Alice", age: 30) +/// let nameAttribute: Attribute = person.name +/// let ageAttribute: Attribute = person.age +/// ``` +/// +/// ## Integration with Rules +/// +/// Create computed attributes using ``Rule`` or ``StatefulRule``: +/// +/// ```swift +/// struct DoubledRule: Rule { +/// typealias Value = Int +/// let source: Attribute +/// +/// func value() -> Int { +/// source.wrappedValue * 2 +/// } +/// } +/// +/// let doubled = Attribute(DoubledRule(source: count)) +/// ``` @frozen @propertyWrapper @dynamicMemberLookup @@ -8,14 +70,30 @@ public struct Attribute { // MARK: - Initializer + /// Creates an attribute from a type-erased identifier. + /// + /// - Parameter identifier: The type-erased attribute identifier public init(identifier: AnyAttribute) { self.identifier = identifier } + /// Creates an attribute by copying another attribute. + /// + /// - Parameter attribute: The attribute to copy public init(_ attribute: Attribute) { self = attribute } + /// Creates an attribute with an initial value. + /// + /// This initializer creates an external attribute that holds the provided value. + /// External attributes are typically used for storing user input or initial state. + /// + /// ```swift + /// let count = Attribute(value: 42) + /// ``` + /// + /// - Parameter value: The initial value for the attribute public init(value: Value) { self = withUnsafePointer(to: value) { valuePointer in withUnsafePointer(to: External()) { bodyPointer in @@ -61,6 +139,18 @@ public struct Attribute { // MARK: - propertyWrapper + /// The current value of the attribute. + /// + /// When used as a property wrapper with `@Attribute`, this provides the underlying value. + /// Getting this value may trigger dependency tracking in the current evaluation context. + /// Setting this value will update the attribute and invalidate any dependents. + /// + /// ```swift + /// @Attribute var count: Int = 0 + /// + /// print(count) // Gets wrappedValue, returns 0 + /// count = 5 // Sets wrappedValue, triggers updates + /// ``` public var wrappedValue: Value { unsafeAddress { OAGGraphGetValue(identifier, type: Value.self) @@ -70,6 +160,18 @@ public struct Attribute { nonmutating set { _ = setValue(newValue) } } + /// The attribute itself when accessed with the `$` prefix. + /// + /// This provides access to the attribute object itself rather than its value, + /// allowing you to pass the reactive attribute to other functions or create + /// derived attributes. + /// + /// ```swift + /// @Attribute var count: Int = 0 + /// + /// let countAttribute = $count // Gets the Attribute object + /// let doubled = countAttribute.map { $0 * 2 } + /// ``` public var projectedValue: Attribute { get { self } set { self = newValue } diff --git a/Sources/OpenAttributeGraph/Attribute/Rule/Rule.swift b/Sources/OpenAttributeGraph/Attribute/Rule/Rule.swift index 4e661ee1..76aae121 100644 --- a/Sources/OpenAttributeGraph/Attribute/Rule/Rule.swift +++ b/Sources/OpenAttributeGraph/Attribute/Rule/Rule.swift @@ -7,9 +7,70 @@ public import OpenAttributeGraphCxx +/// A protocol for defining computed attributes that automatically update when dependencies change. +/// +/// Rules provide a way to create derived attributes that compute their values based on other attributes. +/// When any dependency changes, the rule will automatically recompute its value. +/// +/// ```swift +/// struct DoubledRule: Rule { +/// typealias Value = Int +/// let source: Attribute +/// +/// var value: Int { +/// source.wrappedValue * 2 +/// } +/// } +/// +/// @Attribute var count: Int = 5 +/// let doubled = Attribute(DoubledRule(source: $count)) +/// // doubled.wrappedValue == 10 +/// +/// count = 10 +/// // doubled.wrappedValue automatically becomes 20 +/// ``` +/// +/// ## Key Features +/// +/// - **Automatic dependency tracking**: Dependencies are discovered automatically when accessed +/// - **Lazy evaluation**: Values are only computed when needed +/// - **Caching**: Results are cached until dependencies change +/// - **Efficient updates**: Only recomputes when dependencies actually change +/// +/// ## Implementation Requirements +/// +/// Types conforming to `Rule` must provide: +/// - `Value`: The type of value produced by the rule +/// - `value`: A computed property that returns the current value +/// - `initialValue`: An optional initial value (defaults to `nil`) +/// +/// ## Advanced Usage +/// +/// For rules that need to maintain state between evaluations, see ``StatefulRule``. +/// For rules that can be cached based on their content, make your rule type conform to `Hashable`. public protocol Rule: _AttributeBody { + /// The type of value produced by this rule. associatedtype Value + + /// An optional initial value to use before the rule is first evaluated. + /// + /// If `nil`, the rule will be evaluated immediately when the attribute is created. + /// If non-`nil`, this value will be used initially, and the rule will be evaluated + /// on the next update cycle. static var initialValue: Value? { get } + + /// Computes and returns the current value of the rule. + /// + /// This property should access any attributes or other dependencies needed to compute + /// the result. The attribute graph will automatically track these dependencies and + /// invalidate this rule when any dependency changes. + /// + /// ```swift + /// var value: Int { + /// // Dependencies are automatically tracked + /// return source1.wrappedValue + source2.wrappedValue + /// } + /// ``` var value: Value { get } } diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Architecture.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Architecture.md new file mode 100644 index 00000000..97071478 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Architecture.md @@ -0,0 +1,164 @@ +# Architecture + +Understanding OpenAttributeGraph's three-layer architecture: Attributes, Graph, and Runtime. + +## Overview + +OpenAttributeGraph is built around a three-layer architecture that provides a complete reactive programming system. Each layer serves a specific purpose in the overall framework, working together to deliver high-performance reactive updates. + +## The Three Layers + +### Attribute Layer + +The **Attribute layer** forms the foundation of the reactive system, providing the building blocks for trackable, reactive values. + +#### Core Concepts + +**Property Wrapper Design**: At its heart, ``Attribute`` is a property wrapper that makes any Swift value reactive. When you wrap a value with `@Attribute`, it automatically gains dependency tracking capabilities: + +```swift +@Attribute var count: Int = 0 +``` + +**Type Erasure**: ``AnyAttribute`` provides type-erased access to attributes, enabling runtime flexibility while maintaining type safety where possible. + +**Rule-Based Transformations**: The ``Rule`` and ``StatefulRule`` protocols allow you to create computed attributes that automatically update when their dependencies change: + +```swift +struct DoubledRule: Rule { + typealias Value = Int + let source: Attribute + + func value() -> Int { + source.wrappedValue * 2 + } +} +``` + +**Reference Semantics**: ``WeakAttribute`` and ``OptionalAttribute`` provide safe ways to handle optional and weak references within the attribute system. + +#### Body System + +The attribute body system optimizes performance through: +- **Lazy evaluation**: Values are only computed when needed +- **Caching**: Results are cached until dependencies change +- **Efficient invalidation**: Only affected attributes are marked for recomputation + +### Graph Layer + +The **Graph layer** manages the dependency network between attributes and orchestrates efficient updates. + +#### Dependency Management + +The ``Graph`` maintains a directed acyclic graph (DAG) of attribute dependencies: + +- **Automatic tracking**: Dependencies are discovered automatically when attributes are accessed during rule evaluation +- **Cycle detection**: The system prevents and detects circular dependencies +- **Batch updates**: Multiple changes are batched together for optimal performance + +#### Update Propagation + +When an attribute changes, the graph efficiently propagates updates: + +1. **Mark phase**: Changed attributes are marked as invalid +2. **Sweep phase**: Dependent attributes are transitively marked +3. **Update phase**: Values are recomputed in dependency order + +#### Subgraphs + +``Subgraph`` provides scoped computation contexts that allow: +- **Isolation**: Separate update domains for different parts of your application +- **Performance**: Smaller update scopes reduce computational overhead +- **Testing**: Isolated environments for unit testing + +### Runtime Layer + +The **Runtime layer** provides the low-level type introspection and memory management that makes the higher layers possible. + +#### Type Introspection + +``Metadata`` provides Swift runtime type information: +- **Field enumeration**: Discover the fields of any Swift type at runtime +- **Layout information**: Access memory layout and alignment details +- **Type comparison**: Efficiently compare types and values + +This runtime introspection enables features like automatic KeyPath-based attribute access: + +```swift +@Attribute var person: Person = Person(name: "Alice", age: 30) +let nameAttribute = person.name // Automatic attribute creation via KeyPath +``` + +#### Memory Management + +The runtime layer handles: +- **Pointer arithmetic**: Safe offset calculations for nested attribute access +- **Type-safe casting**: Runtime type validation and casting +- **Value comparison**: Efficient equality checking across different types + +#### Integration with Swift Runtime + +> **Note**: The Runtime layer leverages techniques similar to those found in [wickwirew/Runtime](https://github.com/wickwirew/Runtime) for Swift runtime introspection and type manipulation. + +The system integrates deeply with Swift's runtime to: +- Access private metadata structures safely +- Perform efficient type conversions +- Handle dynamic member lookup for attributes + +## How the Layers Work Together + +### Creating an Attribute + +When you create an attribute, all three layers collaborate: + +1. **Runtime layer**: Introspects the value type and creates metadata +2. **Graph layer**: Allocates space in the dependency graph +3. **Attribute layer**: Wraps the value in a reactive property wrapper + +### Dependency Tracking + +During rule evaluation: + +1. **Attribute layer**: Rules access their dependency attributes +2. **Graph layer**: Records these accesses as dependencies +3. **Runtime layer**: Handles type-safe value extraction and conversion + +### Update Propagation + +When a change occurs: + +1. **Attribute layer**: Detects the value change +2. **Graph layer**: Propagates invalidation through dependencies +3. **Runtime layer**: Provides efficient value comparison to minimize updates + +## Performance Characteristics + +The three-layer architecture enables several performance optimizations: + +- **Minimal allocations**: Attributes reuse storage and minimize memory churn +- **Lazy evaluation**: Computations are deferred until values are actually needed +- **Batch processing**: Multiple updates are processed together +- **Cache efficiency**: Hot paths through the dependency graph are optimized + +## Design Patterns + +The architecture encourages several beneficial patterns: + +### Composition over Inheritance +Attributes compose naturally through rules and transformations rather than class hierarchies. + +### Functional Reactive Programming +The rule system encourages pure, functional transformations of data. + +### Declarative Updates +Changes propagate automatically without explicit update calls. + +## Debugging and Introspection + +Each layer provides debugging capabilities: + +- **Attribute layer**: Inspect individual attribute values and states +- **Graph layer**: Visualize dependency relationships and update cycles +- **Runtime layer**: Examine type metadata and memory layout + +The ``DebugServer`` provides a unified interface for debugging across all layers. \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md new file mode 100644 index 00000000..e2f5f98d --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md @@ -0,0 +1,59 @@ +# ``OpenAttributeGraph`` + +A high-performance reactive programming framework that powers SwiftUI's underlying dependency tracking and update system. + +## Overview + +OpenAttributeGraph is an open source implementation of Apple's private AttributeGraph framework. It provides a reactive programming model built around attributes that automatically track dependencies and efficiently propagate changes through a dependency graph. + +The framework is designed for high performance and powers the reactive updates that make SwiftUI interfaces responsive and efficient. + +## Topics + +### Architecture + +- + +### Core Components + +#### Attributes +- ``Attribute`` +- ``AnyAttribute`` +- ``WeakAttribute`` +- ``AnyWeakAttribute`` +- ``OptionalAttribute`` +- ``AnyOptionalAttribute`` +- ``IndirectAttribute`` + +#### Rules and Transformations +- ``Rule`` +- ``StatefulRule`` +- ``Focus`` +- ``Map`` + +#### Graph Management +- ``Graph`` +- ``Subgraph`` + +#### Runtime Support +- ``Metadata`` +- ``CompareValues`` +- ``TupleType`` + +#### Debugging and Development +- ``DebugServer`` + +### Advanced Topics + +#### Attribute Bodies +- ``AttributeBody`` +- ``AttributeBodyVisitor`` +- ``ObservedAttribute`` + +#### Context Management +- ``RuleContext`` +- ``AnyRuleContext`` + +#### Type System Support +- ``External`` +- ``PointerOffset`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/Runtime/Metadata.swift b/Sources/OpenAttributeGraph/Runtime/Metadata.swift index 0a3ee53a..c8514482 100644 --- a/Sources/OpenAttributeGraph/Runtime/Metadata.swift +++ b/Sources/OpenAttributeGraph/Runtime/Metadata.swift @@ -31,10 +31,30 @@ public func forEachField( } extension Metadata: Swift.Hashable, Swift.CustomStringConvertible { + /// Creates metadata from a Swift type. + /// + /// This initializer allows you to create runtime metadata for any Swift type, + /// which can then be used for type introspection and comparison. + /// + /// ```swift + /// let intMetadata = Metadata(Int.self) + /// let stringMetadata = Metadata(String.self) + /// ``` + /// + /// - Parameter type: The Swift type to create metadata for public init(_ type: any Any.Type) { self.init(rawValue: unsafeBitCast(type, to: UnsafePointer<_Metadata>.self)) } + /// The Swift type represented by this metadata. + /// + /// This property allows you to convert from runtime metadata back to a Swift type, + /// enabling dynamic type operations. + /// + /// ```swift + /// let metadata = Metadata(String.self) + /// let type = metadata.type // Returns String.Type + /// ``` public var type: any Any.Type { unsafeBitCast(rawValue, to: Any.Type.self) } From ca35a14672f82aff9b009119738ac2109928e15f Mon Sep 17 00:00:00 2001 From: Kyle Date: Sat, 6 Sep 2025 18:59:43 +0800 Subject: [PATCH 02/12] Fix swift-docc documentation references - Use Architecture-article anchor for architecture documentation - Update CompareValues reference to compareValues(_:_:mode:) - Fix AttributeBody reference to _AttributeBody --- .../OpenAttributeGraph.docc/OpenAttributeGraph.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md index e2f5f98d..fbd106fb 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md @@ -12,7 +12,7 @@ The framework is designed for high performance and powers the reactive updates t ### Architecture -- +- ### Core Components @@ -37,7 +37,7 @@ The framework is designed for high performance and powers the reactive updates t #### Runtime Support - ``Metadata`` -- ``CompareValues`` +- ``compareValues(_:_:mode:)`` - ``TupleType`` #### Debugging and Development @@ -46,7 +46,7 @@ The framework is designed for high performance and powers the reactive updates t ### Advanced Topics #### Attribute Bodies -- ``AttributeBody`` +- ``_AttributeBody`` - ``AttributeBodyVisitor`` - ``ObservedAttribute`` From a91031011441d7d21344a3c9e69ce257648324af Mon Sep 17 00:00:00 2001 From: Kyle Date: Sat, 6 Sep 2025 20:10:31 +0800 Subject: [PATCH 03/12] Update documentation to match OpenSwiftUI docc format - Replace markdown code fences with indented code blocks (4 spaces) - Update main documentation categories (Architecture -> Essentials) - Follow OpenSwiftUI documentation patterns and conventions - Maintain consistent formatting across all swift-docc files --- .gitignore | 3 +- .../Attribute/Attribute/Attribute.swift | 76 ++++++++----------- .../Attribute/Rule/Rule.swift | 36 ++++----- .../OpenAttributeGraph.docc/Architecture.md | 26 +++---- .../OpenAttributeGraph.md | 4 +- .../OpenAttributeGraph/Runtime/Metadata.swift | 12 +-- 6 files changed, 65 insertions(+), 92 deletions(-) diff --git a/.gitignore b/.gitignore index cc8d7833..4b3e9a5a 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,5 @@ TODO.md .ag_template/ build/ .ag_repo/ -.og_repo/ \ No newline at end of file +.oag_repo/ +.claude diff --git a/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift b/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift index d0c1af7f..d98632bd 100644 --- a/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift +++ b/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift @@ -5,12 +5,10 @@ public import OpenAttributeGraphCxx /// `Attribute` is the core building block of the OpenAttributeGraph reactive system. When you wrap a property /// with `@Attribute`, it becomes reactive and can automatically track dependencies and propagate changes. /// -/// ```swift -/// @Attribute var count: Int = 0 -/// @Attribute var doubledCount: Int = count * 2 -/// -/// count = 5 // doubledCount automatically becomes 10 -/// ``` +/// @Attribute var count: Int = 0 +/// @Attribute var doubledCount: Int = count * 2 +/// +/// count = 5 // doubledCount automatically becomes 10 /// /// ## Key Features /// @@ -24,44 +22,38 @@ public import OpenAttributeGraphCxx /// /// Use `@Attribute` to make any Swift value reactive: /// -/// ```swift -/// struct CounterView { -/// @Attribute var count: Int = 0 -/// -/// var body: some View { -/// Button("Count: \(count)") { -/// count += 1 +/// struct CounterView { +/// @Attribute var count: Int = 0 +/// +/// var body: some View { +/// Button("Count: \(count)") { +/// count += 1 +/// } /// } /// } -/// } -/// ``` /// /// ## Dynamic Member Lookup /// /// Access nested properties as separate attributes: /// -/// ```swift -/// @Attribute var person: Person = Person(name: "Alice", age: 30) -/// let nameAttribute: Attribute = person.name -/// let ageAttribute: Attribute = person.age -/// ``` +/// @Attribute var person: Person = Person(name: "Alice", age: 30) +/// let nameAttribute: Attribute = person.name +/// let ageAttribute: Attribute = person.age /// /// ## Integration with Rules /// /// Create computed attributes using ``Rule`` or ``StatefulRule``: /// -/// ```swift -/// struct DoubledRule: Rule { -/// typealias Value = Int -/// let source: Attribute -/// -/// func value() -> Int { -/// source.wrappedValue * 2 +/// struct DoubledRule: Rule { +/// typealias Value = Int +/// let source: Attribute +/// +/// func value() -> Int { +/// source.wrappedValue * 2 +/// } /// } -/// } /// -/// let doubled = Attribute(DoubledRule(source: count)) -/// ``` +/// let doubled = Attribute(DoubledRule(source: count)) @frozen @propertyWrapper @dynamicMemberLookup @@ -89,9 +81,7 @@ public struct Attribute { /// This initializer creates an external attribute that holds the provided value. /// External attributes are typically used for storing user input or initial state. /// - /// ```swift - /// let count = Attribute(value: 42) - /// ``` + /// let count = Attribute(value: 42) /// /// - Parameter value: The initial value for the attribute public init(value: Value) { @@ -145,12 +135,10 @@ public struct Attribute { /// Getting this value may trigger dependency tracking in the current evaluation context. /// Setting this value will update the attribute and invalidate any dependents. /// - /// ```swift - /// @Attribute var count: Int = 0 - /// - /// print(count) // Gets wrappedValue, returns 0 - /// count = 5 // Sets wrappedValue, triggers updates - /// ``` + /// @Attribute var count: Int = 0 + /// + /// print(count) // Gets wrappedValue, returns 0 + /// count = 5 // Sets wrappedValue, triggers updates public var wrappedValue: Value { unsafeAddress { OAGGraphGetValue(identifier, type: Value.self) @@ -166,12 +154,10 @@ public struct Attribute { /// allowing you to pass the reactive attribute to other functions or create /// derived attributes. /// - /// ```swift - /// @Attribute var count: Int = 0 - /// - /// let countAttribute = $count // Gets the Attribute object - /// let doubled = countAttribute.map { $0 * 2 } - /// ``` + /// @Attribute var count: Int = 0 + /// + /// let countAttribute = $count // Gets the Attribute object + /// let doubled = countAttribute.map { $0 * 2 } public var projectedValue: Attribute { get { self } set { self = newValue } diff --git a/Sources/OpenAttributeGraph/Attribute/Rule/Rule.swift b/Sources/OpenAttributeGraph/Attribute/Rule/Rule.swift index 76aae121..18100808 100644 --- a/Sources/OpenAttributeGraph/Attribute/Rule/Rule.swift +++ b/Sources/OpenAttributeGraph/Attribute/Rule/Rule.swift @@ -12,23 +12,21 @@ public import OpenAttributeGraphCxx /// Rules provide a way to create derived attributes that compute their values based on other attributes. /// When any dependency changes, the rule will automatically recompute its value. /// -/// ```swift -/// struct DoubledRule: Rule { -/// typealias Value = Int -/// let source: Attribute -/// -/// var value: Int { -/// source.wrappedValue * 2 +/// struct DoubledRule: Rule { +/// typealias Value = Int +/// let source: Attribute +/// +/// var value: Int { +/// source.wrappedValue * 2 +/// } /// } -/// } /// -/// @Attribute var count: Int = 5 -/// let doubled = Attribute(DoubledRule(source: $count)) -/// // doubled.wrappedValue == 10 +/// @Attribute var count: Int = 5 +/// let doubled = Attribute(DoubledRule(source: $count)) +/// // doubled.wrappedValue == 10 /// -/// count = 10 -/// // doubled.wrappedValue automatically becomes 20 -/// ``` +/// count = 10 +/// // doubled.wrappedValue automatically becomes 20 /// /// ## Key Features /// @@ -65,12 +63,10 @@ public protocol Rule: _AttributeBody { /// the result. The attribute graph will automatically track these dependencies and /// invalidate this rule when any dependency changes. /// - /// ```swift - /// var value: Int { - /// // Dependencies are automatically tracked - /// return source1.wrappedValue + source2.wrappedValue - /// } - /// ``` + /// var value: Int { + /// // Dependencies are automatically tracked + /// return source1.wrappedValue + source2.wrappedValue + /// } var value: Value { get } } diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Architecture.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Architecture.md index 97071478..e62bdbef 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Architecture.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Architecture.md @@ -16,24 +16,20 @@ The **Attribute layer** forms the foundation of the reactive system, providing t **Property Wrapper Design**: At its heart, ``Attribute`` is a property wrapper that makes any Swift value reactive. When you wrap a value with `@Attribute`, it automatically gains dependency tracking capabilities: -```swift -@Attribute var count: Int = 0 -``` + @Attribute var count: Int = 0 **Type Erasure**: ``AnyAttribute`` provides type-erased access to attributes, enabling runtime flexibility while maintaining type safety where possible. **Rule-Based Transformations**: The ``Rule`` and ``StatefulRule`` protocols allow you to create computed attributes that automatically update when their dependencies change: -```swift -struct DoubledRule: Rule { - typealias Value = Int - let source: Attribute - - func value() -> Int { - source.wrappedValue * 2 + struct DoubledRule: Rule { + typealias Value = Int + let source: Attribute + + func value() -> Int { + source.wrappedValue * 2 + } } -} -``` **Reference Semantics**: ``WeakAttribute`` and ``OptionalAttribute`` provide safe ways to handle optional and weak references within the attribute system. @@ -84,10 +80,8 @@ The **Runtime layer** provides the low-level type introspection and memory manag This runtime introspection enables features like automatic KeyPath-based attribute access: -```swift -@Attribute var person: Person = Person(name: "Alice", age: 30) -let nameAttribute = person.name // Automatic attribute creation via KeyPath -``` + @Attribute var person: Person = Person(name: "Alice", age: 30) + let nameAttribute = person.name // Automatic attribute creation via KeyPath #### Memory Management diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md index fbd106fb..e41db835 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md @@ -10,7 +10,7 @@ The framework is designed for high performance and powers the reactive updates t ## Topics -### Architecture +### Essentials - @@ -56,4 +56,4 @@ The framework is designed for high performance and powers the reactive updates t #### Type System Support - ``External`` -- ``PointerOffset`` \ No newline at end of file +- ``PointerOffset`` diff --git a/Sources/OpenAttributeGraph/Runtime/Metadata.swift b/Sources/OpenAttributeGraph/Runtime/Metadata.swift index c8514482..a4261b1c 100644 --- a/Sources/OpenAttributeGraph/Runtime/Metadata.swift +++ b/Sources/OpenAttributeGraph/Runtime/Metadata.swift @@ -36,10 +36,8 @@ extension Metadata: Swift.Hashable, Swift.CustomStringConvertible { /// This initializer allows you to create runtime metadata for any Swift type, /// which can then be used for type introspection and comparison. /// - /// ```swift - /// let intMetadata = Metadata(Int.self) - /// let stringMetadata = Metadata(String.self) - /// ``` + /// let intMetadata = Metadata(Int.self) + /// let stringMetadata = Metadata(String.self) /// /// - Parameter type: The Swift type to create metadata for public init(_ type: any Any.Type) { @@ -51,10 +49,8 @@ extension Metadata: Swift.Hashable, Swift.CustomStringConvertible { /// This property allows you to convert from runtime metadata back to a Swift type, /// enabling dynamic type operations. /// - /// ```swift - /// let metadata = Metadata(String.self) - /// let type = metadata.type // Returns String.Type - /// ``` + /// let metadata = Metadata(String.self) + /// let type = metadata.type // Returns String.Type public var type: any Any.Type { unsafeBitCast(rawValue, to: Any.Type.self) } From 11b246946cc8b70ce331247711ee45567365cb19 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sat, 6 Sep 2025 19:18:06 +0800 Subject: [PATCH 04/12] Refactor documentation into separate topic articles - Create Core-Components.md article for fundamental types and APIs - Create Advanced-Topics.md article for specialized functionality - Remove nested subheadings (####) from main documentation - Organize topics into logical groups with dedicated articles - Improve documentation discoverability and navigation --- .../Advanced-Topics.md | 28 +++++++++++ .../Core-Components.md | 49 +++++++++++++++++++ .../OpenAttributeGraph.docc/Info.plist | 12 +++++ .../OpenAttributeGraph.md | 44 ++--------------- 4 files changed, 93 insertions(+), 40 deletions(-) create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Advanced-Topics.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Core-Components.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Info.plist diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Advanced-Topics.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Advanced-Topics.md new file mode 100644 index 00000000..b0debd9c --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Advanced-Topics.md @@ -0,0 +1,28 @@ +# Advanced Topics + +Advanced features and implementation details for sophisticated use cases. + +## Overview + +These advanced topics cover specialized functionality and implementation details that are useful for complex scenarios and deep integration with OpenAttributeGraph's reactive system. + +## Attribute Bodies + +Low-level attribute implementation and visitor patterns for advanced attribute manipulation. + +- ``AttributeBodyVisitor`` - Protocol for visiting and inspecting attribute bodies +- ``ObservedAttribute`` - Attribute wrapper for observing changes in other attributes + +## Context Management + +Types for managing evaluation contexts and rule execution environments. + +- ``RuleContext`` - Context object providing access to rule evaluation state +- ``AnyRuleContext`` - Type-erased rule context for runtime flexibility + +## Type System Support + +Utilities for working with external values and memory layout manipulation. + +- ``External`` - Wrapper for external values not managed by the attribute graph +- ``PointerOffset`` - Type-safe pointer arithmetic for nested attribute access \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Core-Components.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Core-Components.md new file mode 100644 index 00000000..31561bba --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Core-Components.md @@ -0,0 +1,49 @@ +# Core Components + +The fundamental building blocks of OpenAttributeGraph's reactive programming system. + +## Overview + +OpenAttributeGraph provides a comprehensive set of components for building reactive applications. These core components work together to provide automatic dependency tracking, efficient updates, and a clean programming model. + +## Attributes + +The foundation of the reactive system, providing property wrappers and type-erased access to reactive values. + +- ``Attribute`` - The primary property wrapper for reactive values +- ``AnyAttribute`` - Type-erased attribute for runtime flexibility +- ``WeakAttribute`` - Weak reference attribute wrapper +- ``AnyWeakAttribute`` - Type-erased weak attribute +- ``OptionalAttribute`` - Optional value attribute wrapper +- ``AnyOptionalAttribute`` - Type-erased optional attribute +- ``IndirectAttribute`` - Indirect attribute for complex reference scenarios + +## Rules and Transformations + +Protocols and types for creating computed attributes that derive their values from other attributes. + +- ``Rule`` - Protocol for stateless computed attributes +- ``StatefulRule`` - Protocol for stateful computed attributes +- ``Focus`` - Rule for focusing on part of an attribute's value +- ``Map`` - Rule for transforming attribute values + +## Graph Management + +Types that manage the dependency graph and coordinate updates across attributes. + +- ``Graph`` - Central coordinator for attribute relationships and updates +- ``Subgraph`` - Scoped computation context for isolated attribute groups + +## Runtime Support + +Low-level utilities for type introspection, comparison, and memory management. + +- ``Metadata`` - Swift runtime type information and reflection +- ``compareValues(_:_:mode:)`` - Efficient value comparison across types +- ``TupleType`` - Runtime support for tuple types and operations + +## Debugging and Development + +Tools for debugging attribute graphs and monitoring performance. + +- ``DebugServer`` - Server for debugging and introspecting attribute graphs \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Info.plist b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Info.plist new file mode 100644 index 00000000..95dc4559 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Info.plist @@ -0,0 +1,12 @@ + + + + + CFBundleName + OpenAttributeGraph + CFBundleDisplayName + OpenAttributeGraph + CDDefaultCodeListingLanguage + swift + + diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md index e41db835..a0ed8939 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md @@ -1,10 +1,10 @@ # ``OpenAttributeGraph`` -A high-performance reactive programming framework that powers SwiftUI's underlying dependency tracking and update system. +A high-performance reactive programming framework that powers OpebSwiftUI's underlying dependency tracking and update system. ## Overview -OpenAttributeGraph is an open source implementation of Apple's private AttributeGraph framework. It provides a reactive programming model built around attributes that automatically track dependencies and efficiently propagate changes through a dependency graph. +It provides a reactive programming model built around attributes that automatically track dependencies and efficiently propagate changes through a dependency graph. The framework is designed for high performance and powers the reactive updates that make SwiftUI interfaces responsive and efficient. @@ -16,44 +16,8 @@ The framework is designed for high performance and powers the reactive updates t ### Core Components -#### Attributes -- ``Attribute`` -- ``AnyAttribute`` -- ``WeakAttribute`` -- ``AnyWeakAttribute`` -- ``OptionalAttribute`` -- ``AnyOptionalAttribute`` -- ``IndirectAttribute`` - -#### Rules and Transformations -- ``Rule`` -- ``StatefulRule`` -- ``Focus`` -- ``Map`` - -#### Graph Management -- ``Graph`` -- ``Subgraph`` - -#### Runtime Support -- ``Metadata`` -- ``compareValues(_:_:mode:)`` -- ``TupleType`` - -#### Debugging and Development -- ``DebugServer`` +- ### Advanced Topics -#### Attribute Bodies -- ``_AttributeBody`` -- ``AttributeBodyVisitor`` -- ``ObservedAttribute`` - -#### Context Management -- ``RuleContext`` -- ``AnyRuleContext`` - -#### Type System Support -- ``External`` -- ``PointerOffset`` +- From 29a65b68640d63c348b0ecc6d64e712e052cd8fa Mon Sep 17 00:00:00 2001 From: Kyle Date: Sat, 6 Sep 2025 19:35:55 +0800 Subject: [PATCH 05/12] Fix documentation references and formatting - Rename Core-Components.md to CoreComponents.md (remove hyphens) - Rename Advanced-Topics.md to AdvancedTopics.md (remove hyphens) - Update article references in OpenAttributeGraph.md to match filenames - Remove Architecture-article suffix, use Architecture directly - Remove all ** bold formatting from markdown articles - Update article titles to match filename conventions --- .../{Advanced-Topics.md => AdvancedTopics.md} | 2 +- .../OpenAttributeGraph.docc/Architecture.md | 82 +++++++++---------- .../{Core-Components.md => CoreComponents.md} | 2 +- .../OpenAttributeGraph.md | 6 +- 4 files changed, 46 insertions(+), 46 deletions(-) rename Sources/OpenAttributeGraph/OpenAttributeGraph.docc/{Advanced-Topics.md => AdvancedTopics.md} (98%) rename Sources/OpenAttributeGraph/OpenAttributeGraph.docc/{Core-Components.md => CoreComponents.md} (99%) diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Advanced-Topics.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/AdvancedTopics.md similarity index 98% rename from Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Advanced-Topics.md rename to Sources/OpenAttributeGraph/OpenAttributeGraph.docc/AdvancedTopics.md index b0debd9c..0d9a4592 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Advanced-Topics.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/AdvancedTopics.md @@ -1,4 +1,4 @@ -# Advanced Topics +# AdvancedTopics Advanced features and implementation details for sophisticated use cases. diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Architecture.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Architecture.md index e62bdbef..0a8be2fd 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Architecture.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Architecture.md @@ -14,13 +14,13 @@ The **Attribute layer** forms the foundation of the reactive system, providing t #### Core Concepts -**Property Wrapper Design**: At its heart, ``Attribute`` is a property wrapper that makes any Swift value reactive. When you wrap a value with `@Attribute`, it automatically gains dependency tracking capabilities: +Property Wrapper Design: At its heart, ``Attribute`` is a property wrapper that makes any Swift value reactive. When you wrap a value with `@Attribute`, it automatically gains dependency tracking capabilities: @Attribute var count: Int = 0 -**Type Erasure**: ``AnyAttribute`` provides type-erased access to attributes, enabling runtime flexibility while maintaining type safety where possible. +Type Erasure: ``AnyAttribute`` provides type-erased access to attributes, enabling runtime flexibility while maintaining type safety where possible. -**Rule-Based Transformations**: The ``Rule`` and ``StatefulRule`` protocols allow you to create computed attributes that automatically update when their dependencies change: +Rule-Based Transformations: The ``Rule`` and ``StatefulRule`` protocols allow you to create computed attributes that automatically update when their dependencies change: struct DoubledRule: Rule { typealias Value = Int @@ -31,52 +31,52 @@ The **Attribute layer** forms the foundation of the reactive system, providing t } } -**Reference Semantics**: ``WeakAttribute`` and ``OptionalAttribute`` provide safe ways to handle optional and weak references within the attribute system. +Reference Semantics: ``WeakAttribute`` and ``OptionalAttribute`` provide safe ways to handle optional and weak references within the attribute system. #### Body System The attribute body system optimizes performance through: -- **Lazy evaluation**: Values are only computed when needed -- **Caching**: Results are cached until dependencies change -- **Efficient invalidation**: Only affected attributes are marked for recomputation +- Lazy evaluation: Values are only computed when needed +- Caching: Results are cached until dependencies change +- Efficient invalidation: Only affected attributes are marked for recomputation ### Graph Layer -The **Graph layer** manages the dependency network between attributes and orchestrates efficient updates. +The Graph layer manages the dependency network between attributes and orchestrates efficient updates. #### Dependency Management The ``Graph`` maintains a directed acyclic graph (DAG) of attribute dependencies: -- **Automatic tracking**: Dependencies are discovered automatically when attributes are accessed during rule evaluation -- **Cycle detection**: The system prevents and detects circular dependencies -- **Batch updates**: Multiple changes are batched together for optimal performance +- Automatic tracking: Dependencies are discovered automatically when attributes are accessed during rule evaluation +- Cycle detection: The system prevents and detects circular dependencies +- Batch updates: Multiple changes are batched together for optimal performance #### Update Propagation When an attribute changes, the graph efficiently propagates updates: -1. **Mark phase**: Changed attributes are marked as invalid -2. **Sweep phase**: Dependent attributes are transitively marked -3. **Update phase**: Values are recomputed in dependency order +1. Mark phase: Changed attributes are marked as invalid +2. Sweep phase: Dependent attributes are transitively marked +3. Update phase: Values are recomputed in dependency order #### Subgraphs ``Subgraph`` provides scoped computation contexts that allow: -- **Isolation**: Separate update domains for different parts of your application -- **Performance**: Smaller update scopes reduce computational overhead -- **Testing**: Isolated environments for unit testing +- Isolation: Separate update domains for different parts of your application +- Performance: Smaller update scopes reduce computational overhead +- Testing: Isolated environments for unit testing ### Runtime Layer -The **Runtime layer** provides the low-level type introspection and memory management that makes the higher layers possible. +The Runtime layer provides the low-level type introspection and memory management that makes the higher layers possible. #### Type Introspection ``Metadata`` provides Swift runtime type information: -- **Field enumeration**: Discover the fields of any Swift type at runtime -- **Layout information**: Access memory layout and alignment details -- **Type comparison**: Efficiently compare types and values +- Field enumeration: Discover the fields of any Swift type at runtime +- Layout information: Access memory layout and alignment details +- Type comparison: Efficiently compare types and values This runtime introspection enables features like automatic KeyPath-based attribute access: @@ -86,13 +86,13 @@ This runtime introspection enables features like automatic KeyPath-based attribu #### Memory Management The runtime layer handles: -- **Pointer arithmetic**: Safe offset calculations for nested attribute access -- **Type-safe casting**: Runtime type validation and casting -- **Value comparison**: Efficient equality checking across different types +- Pointer arithmetic: Safe offset calculations for nested attribute access +- Type-safe casting: Runtime type validation and casting +- Value comparison: Efficient equality checking across different types #### Integration with Swift Runtime -> **Note**: The Runtime layer leverages techniques similar to those found in [wickwirew/Runtime](https://github.com/wickwirew/Runtime) for Swift runtime introspection and type manipulation. +> Note: The Runtime layer leverages techniques similar to those found in [wickwirew/Runtime](https://github.com/wickwirew/Runtime) for Swift runtime introspection and type manipulation. The system integrates deeply with Swift's runtime to: - Access private metadata structures safely @@ -105,34 +105,34 @@ The system integrates deeply with Swift's runtime to: When you create an attribute, all three layers collaborate: -1. **Runtime layer**: Introspects the value type and creates metadata -2. **Graph layer**: Allocates space in the dependency graph -3. **Attribute layer**: Wraps the value in a reactive property wrapper +1. Runtime layer: Introspects the value type and creates metadata +2. Graph layer: Allocates space in the dependency graph +3. Attribute layer: Wraps the value in a reactive property wrapper ### Dependency Tracking During rule evaluation: -1. **Attribute layer**: Rules access their dependency attributes -2. **Graph layer**: Records these accesses as dependencies -3. **Runtime layer**: Handles type-safe value extraction and conversion +1. Attribute layer: Rules access their dependency attributes +2. Graph layer: Records these accesses as dependencies +3. Runtime layer: Handles type-safe value extraction and conversion ### Update Propagation When a change occurs: -1. **Attribute layer**: Detects the value change -2. **Graph layer**: Propagates invalidation through dependencies -3. **Runtime layer**: Provides efficient value comparison to minimize updates +1. Attribute layer: Detects the value change +2. Graph layer: Propagates invalidation through dependencies +3. Runtime layer: Provides efficient value comparison to minimize updates ## Performance Characteristics The three-layer architecture enables several performance optimizations: -- **Minimal allocations**: Attributes reuse storage and minimize memory churn -- **Lazy evaluation**: Computations are deferred until values are actually needed -- **Batch processing**: Multiple updates are processed together -- **Cache efficiency**: Hot paths through the dependency graph are optimized +- Minimal allocations: Attributes reuse storage and minimize memory churn +- Lazy evaluation: Computations are deferred until values are actually needed +- Batch processing: Multiple updates are processed together +- Cache efficiency: Hot paths through the dependency graph are optimized ## Design Patterns @@ -151,8 +151,8 @@ Changes propagate automatically without explicit update calls. Each layer provides debugging capabilities: -- **Attribute layer**: Inspect individual attribute values and states -- **Graph layer**: Visualize dependency relationships and update cycles -- **Runtime layer**: Examine type metadata and memory layout +- Attribute layer: Inspect individual attribute values and states +- Graph layer: Visualize dependency relationships and update cycles +- Runtime layer: Examine type metadata and memory layout The ``DebugServer`` provides a unified interface for debugging across all layers. \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Core-Components.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/CoreComponents.md similarity index 99% rename from Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Core-Components.md rename to Sources/OpenAttributeGraph/OpenAttributeGraph.docc/CoreComponents.md index 31561bba..261cb1ee 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Core-Components.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/CoreComponents.md @@ -1,4 +1,4 @@ -# Core Components +# CoreComponents The fundamental building blocks of OpenAttributeGraph's reactive programming system. diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md index a0ed8939..d889cd32 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md @@ -12,12 +12,12 @@ The framework is designed for high performance and powers the reactive updates t ### Essentials -- +- ### Core Components -- +- ### Advanced Topics -- +- From 7986436f8b5952267d7cb87b4130658fa16b9d5e Mon Sep 17 00:00:00 2001 From: Kyle Date: Sat, 6 Sep 2025 19:36:58 +0800 Subject: [PATCH 06/12] Update Architecture.md to remove layer-specific references - Remove 'three-layer architecture' from title and overview - Change 'The Three Layers' section to 'Core Architecture' - Remove 'The **Attribute layer**' bold formatting - Remove DebugServer unified interface statement - Simplify architecture description while maintaining technical accuracy --- .../OpenAttributeGraph.docc/Architecture.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Architecture.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Architecture.md index 0a8be2fd..2cc7d1de 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Architecture.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Architecture.md @@ -1,16 +1,16 @@ # Architecture -Understanding OpenAttributeGraph's three-layer architecture: Attributes, Graph, and Runtime. +Understanding OpenAttributeGraph's architecture: Attributes, Graph, and Runtime. ## Overview -OpenAttributeGraph is built around a three-layer architecture that provides a complete reactive programming system. Each layer serves a specific purpose in the overall framework, working together to deliver high-performance reactive updates. +OpenAttributeGraph is built around an architecture that provides a complete reactive programming system. Each layer serves a specific purpose in the overall framework, working together to deliver high-performance reactive updates. -## The Three Layers +## Core Architecture ### Attribute Layer -The **Attribute layer** forms the foundation of the reactive system, providing the building blocks for trackable, reactive values. +The Attribute layer forms the foundation of the reactive system, providing the building blocks for trackable, reactive values. #### Core Concepts @@ -153,6 +153,4 @@ Each layer provides debugging capabilities: - Attribute layer: Inspect individual attribute values and states - Graph layer: Visualize dependency relationships and update cycles -- Runtime layer: Examine type metadata and memory layout - -The ``DebugServer`` provides a unified interface for debugging across all layers. \ No newline at end of file +- Runtime layer: Examine type metadata and memory layout \ No newline at end of file From 8cc5128c3a8229f81698b56a63050775c551d3d1 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sat, 6 Sep 2025 20:16:37 +0800 Subject: [PATCH 07/12] Refactor API documentation into separate DocC extension files - Create dedicated extension files for major APIs: * Attribute.md - Comprehensive property wrapper documentation * Rule.md - Computed attribute protocol documentation * Metadata.md - Runtime type introspection documentation - Simplify source code documentation to brief summaries - Move detailed examples and usage patterns to extension files - Follow OpenSwiftUI documentation organization patterns - Improve documentation discoverability with Topics sections --- .../Attribute/Attribute/Attribute.swift | 76 ----------- .../Attribute/Rule/Rule.swift | 51 -------- .../OpenAttributeGraph.docc/Attribute.md | 118 ++++++++++++++++++ .../OpenAttributeGraph.docc/Metadata.md | 43 +++++++ .../OpenAttributeGraph.docc/Rule.md | 60 +++++++++ .../OpenAttributeGraph/Runtime/Metadata.swift | 12 -- 6 files changed, 221 insertions(+), 139 deletions(-) create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Metadata.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Rule.md diff --git a/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift b/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift index d98632bd..0425167a 100644 --- a/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift +++ b/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift @@ -1,59 +1,6 @@ public import OpenAttributeGraphCxx /// A reactive property wrapper that automatically tracks dependencies and manages value updates. -/// -/// `Attribute` is the core building block of the OpenAttributeGraph reactive system. When you wrap a property -/// with `@Attribute`, it becomes reactive and can automatically track dependencies and propagate changes. -/// -/// @Attribute var count: Int = 0 -/// @Attribute var doubledCount: Int = count * 2 -/// -/// count = 5 // doubledCount automatically becomes 10 -/// -/// ## Key Features -/// -/// - **Automatic dependency tracking**: Attributes automatically discover their dependencies -/// - **Efficient updates**: Only affected attributes are recomputed when changes occur -/// - **Type safety**: Full Swift type safety with compile-time checking -/// - **Dynamic member lookup**: Access nested properties as reactive attributes -/// - **Property wrapper syntax**: Clean, declarative syntax using `@Attribute` -/// -/// ## Property Wrapper Usage -/// -/// Use `@Attribute` to make any Swift value reactive: -/// -/// struct CounterView { -/// @Attribute var count: Int = 0 -/// -/// var body: some View { -/// Button("Count: \(count)") { -/// count += 1 -/// } -/// } -/// } -/// -/// ## Dynamic Member Lookup -/// -/// Access nested properties as separate attributes: -/// -/// @Attribute var person: Person = Person(name: "Alice", age: 30) -/// let nameAttribute: Attribute = person.name -/// let ageAttribute: Attribute = person.age -/// -/// ## Integration with Rules -/// -/// Create computed attributes using ``Rule`` or ``StatefulRule``: -/// -/// struct DoubledRule: Rule { -/// typealias Value = Int -/// let source: Attribute -/// -/// func value() -> Int { -/// source.wrappedValue * 2 -/// } -/// } -/// -/// let doubled = Attribute(DoubledRule(source: count)) @frozen @propertyWrapper @dynamicMemberLookup @@ -78,11 +25,6 @@ public struct Attribute { /// Creates an attribute with an initial value. /// - /// This initializer creates an external attribute that holds the provided value. - /// External attributes are typically used for storing user input or initial state. - /// - /// let count = Attribute(value: 42) - /// /// - Parameter value: The initial value for the attribute public init(value: Value) { self = withUnsafePointer(to: value) { valuePointer in @@ -130,15 +72,6 @@ public struct Attribute { // MARK: - propertyWrapper /// The current value of the attribute. - /// - /// When used as a property wrapper with `@Attribute`, this provides the underlying value. - /// Getting this value may trigger dependency tracking in the current evaluation context. - /// Setting this value will update the attribute and invalidate any dependents. - /// - /// @Attribute var count: Int = 0 - /// - /// print(count) // Gets wrappedValue, returns 0 - /// count = 5 // Sets wrappedValue, triggers updates public var wrappedValue: Value { unsafeAddress { OAGGraphGetValue(identifier, type: Value.self) @@ -149,15 +82,6 @@ public struct Attribute { } /// The attribute itself when accessed with the `$` prefix. - /// - /// This provides access to the attribute object itself rather than its value, - /// allowing you to pass the reactive attribute to other functions or create - /// derived attributes. - /// - /// @Attribute var count: Int = 0 - /// - /// let countAttribute = $count // Gets the Attribute object - /// let doubled = countAttribute.map { $0 * 2 } public var projectedValue: Attribute { get { self } set { self = newValue } diff --git a/Sources/OpenAttributeGraph/Attribute/Rule/Rule.swift b/Sources/OpenAttributeGraph/Attribute/Rule/Rule.swift index 18100808..cf9295b9 100644 --- a/Sources/OpenAttributeGraph/Attribute/Rule/Rule.swift +++ b/Sources/OpenAttributeGraph/Attribute/Rule/Rule.swift @@ -8,65 +8,14 @@ public import OpenAttributeGraphCxx /// A protocol for defining computed attributes that automatically update when dependencies change. -/// -/// Rules provide a way to create derived attributes that compute their values based on other attributes. -/// When any dependency changes, the rule will automatically recompute its value. -/// -/// struct DoubledRule: Rule { -/// typealias Value = Int -/// let source: Attribute -/// -/// var value: Int { -/// source.wrappedValue * 2 -/// } -/// } -/// -/// @Attribute var count: Int = 5 -/// let doubled = Attribute(DoubledRule(source: $count)) -/// // doubled.wrappedValue == 10 -/// -/// count = 10 -/// // doubled.wrappedValue automatically becomes 20 -/// -/// ## Key Features -/// -/// - **Automatic dependency tracking**: Dependencies are discovered automatically when accessed -/// - **Lazy evaluation**: Values are only computed when needed -/// - **Caching**: Results are cached until dependencies change -/// - **Efficient updates**: Only recomputes when dependencies actually change -/// -/// ## Implementation Requirements -/// -/// Types conforming to `Rule` must provide: -/// - `Value`: The type of value produced by the rule -/// - `value`: A computed property that returns the current value -/// - `initialValue`: An optional initial value (defaults to `nil`) -/// -/// ## Advanced Usage -/// -/// For rules that need to maintain state between evaluations, see ``StatefulRule``. -/// For rules that can be cached based on their content, make your rule type conform to `Hashable`. public protocol Rule: _AttributeBody { /// The type of value produced by this rule. associatedtype Value /// An optional initial value to use before the rule is first evaluated. - /// - /// If `nil`, the rule will be evaluated immediately when the attribute is created. - /// If non-`nil`, this value will be used initially, and the rule will be evaluated - /// on the next update cycle. static var initialValue: Value? { get } /// Computes and returns the current value of the rule. - /// - /// This property should access any attributes or other dependencies needed to compute - /// the result. The attribute graph will automatically track these dependencies and - /// invalidate this rule when any dependency changes. - /// - /// var value: Int { - /// // Dependencies are automatically tracked - /// return source1.wrappedValue + source2.wrappedValue - /// } var value: Value { get } } diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute.md new file mode 100644 index 00000000..ae762a21 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute.md @@ -0,0 +1,118 @@ +# ``Attribute`` + +A reactive property wrapper that automatically tracks dependencies and manages value updates. + +## Overview + +`Attribute` is the core building block of the OpenAttributeGraph reactive system. When you wrap a property with `@Attribute`, it becomes reactive and can automatically track dependencies and propagate changes. + + @Attribute var count: Int = 0 + @Attribute var doubledCount: Int = count * 2 + + count = 5 // doubledCount automatically becomes 10 + +## Key Features + +- Automatic dependency tracking: Attributes automatically discover their dependencies +- Efficient updates: Only affected attributes are recomputed when changes occur +- Type safety: Full Swift type safety with compile-time checking +- Dynamic member lookup: Access nested properties as reactive attributes +- Property wrapper syntax: Clean, declarative syntax using `@Attribute` + +## Property Wrapper Usage + +Use `@Attribute` to make any Swift value reactive: + + struct CounterView { + @Attribute var count: Int = 0 + + var body: some View { + Button("Count: \(count)") { + count += 1 + } + } + } + +## Dynamic Member Lookup + +Access nested properties as separate attributes: + + @Attribute var person: Person = Person(name: "Alice", age: 30) + let nameAttribute: Attribute = person.name + let ageAttribute: Attribute = person.age + +## Integration with Rules + +Create computed attributes using ``Rule`` or ``StatefulRule``: + + struct DoubledRule: Rule { + typealias Value = Int + let source: Attribute + + func value() -> Int { + source.wrappedValue * 2 + } + } + + let doubled = Attribute(DoubledRule(source: count)) + +## Topics + +### Creating Attributes + +- ``init(identifier:)`` +- ``init(_:)`` +- ``init(value:)`` +- ``init(type:)`` + +### Property Wrapper + +- ``wrappedValue`` +- ``projectedValue`` + +### Dynamic Member Access + +- ``subscript(dynamicMember:)`` +- ``subscript(keyPath:)`` +- ``subscript(offset:)`` + +### Type Transformations + +- ``unsafeCast(to:)`` +- ``unsafeOffset(at:as:)`` +- ``applying(offset:)`` + +### Graph Integration + +- ``graph`` +- ``subgraph`` + +### Value Management + +- ``value`` +- ``valueState`` +- ``valueAndFlags(options:)`` +- ``changedValue(options:)`` +- ``setValue(_:)`` +- ``hasValue`` +- ``updateValue()`` +- ``prefetchValue()`` +- ``invalidateValue()`` +- ``validate()`` + +### Input Management + +- ``addInput(_:options:token:)-9c3h6`` +- ``addInput(_:options:token:)-7u9k3`` + +### Flags and State + +- ``Flags`` +- ``flags`` +- ``setFlags(_:mask:)`` + +### Advanced Operations + +- ``visitBody(_:)`` +- ``mutateBody(as:invalidating:_:)`` +- ``breadthFirstSearch(options:_:)`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Metadata.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Metadata.md new file mode 100644 index 00000000..ea3f4d43 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Metadata.md @@ -0,0 +1,43 @@ +# ``Metadata`` + +Swift runtime type information and reflection capabilities for OpenAttributeGraph. + +## Overview + +`Metadata` provides access to Swift's runtime type system, enabling type introspection and dynamic operations that power OpenAttributeGraph's reactive system. + + let intMetadata = Metadata(Int.self) + let stringMetadata = Metadata(String.self) + + let metadata = Metadata(String.self) + let type = metadata.type // Returns String.Type + +## Key Features + +- Runtime type introspection: Access Swift type metadata at runtime +- Field enumeration: Discover the fields of any Swift type +- Type comparison: Efficient equality checking across different types +- Memory layout: Access memory layout and alignment details + +## Usage with Attributes + +Metadata enables OpenAttributeGraph to perform type-safe operations on attributes with different value types, supporting features like automatic KeyPath-based attribute access and efficient value comparison. + +## Topics + +### Creating Metadata + +- ``init(_:)`` + +### Type Information + +- ``type`` +- ``description`` + +### Field Introspection + +- ``forEachField(options:do:)`` + +### Global Functions + +- ``forEachField(of:do:)`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Rule.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Rule.md new file mode 100644 index 00000000..f639ca70 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Rule.md @@ -0,0 +1,60 @@ +# ``Rule`` + +A protocol for defining computed attributes that automatically update when dependencies change. + +## Overview + +Rules provide a way to create derived attributes that compute their values based on other attributes. When any dependency changes, the rule will automatically recompute its value. + + struct DoubledRule: Rule { + typealias Value = Int + let source: Attribute + + var value: Int { + source.wrappedValue * 2 + } + } + + @Attribute var count: Int = 5 + let doubled = Attribute(DoubledRule(source: $count)) + // doubled.wrappedValue == 10 + + count = 10 + // doubled.wrappedValue automatically becomes 20 + +## Key Features + +- Automatic dependency tracking: Dependencies are discovered automatically when accessed +- Lazy evaluation: Values are only computed when needed +- Caching: Results are cached until dependencies change +- Efficient updates: Only recomputes when dependencies actually change + +## Implementation Requirements + +Types conforming to `Rule` must provide: +- `Value`: The type of value produced by the rule +- `value`: A computed property that returns the current value +- `initialValue`: An optional initial value (defaults to `nil`) + +## Advanced Usage + +For rules that need to maintain state between evaluations, see ``StatefulRule``. +For rules that can be cached based on their content, make your rule type conform to `Hashable`. + +## Topics + +### Protocol Requirements + +- ``Value`` +- ``initialValue`` +- ``value`` + +### Context Access + +- ``attribute`` +- ``context`` + +### Cached Evaluation + +- ``cachedValue(options:owner:)`` +- ``cachedValueIfExists(options:owner:)`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/Runtime/Metadata.swift b/Sources/OpenAttributeGraph/Runtime/Metadata.swift index a4261b1c..020d8238 100644 --- a/Sources/OpenAttributeGraph/Runtime/Metadata.swift +++ b/Sources/OpenAttributeGraph/Runtime/Metadata.swift @@ -33,24 +33,12 @@ public func forEachField( extension Metadata: Swift.Hashable, Swift.CustomStringConvertible { /// Creates metadata from a Swift type. /// - /// This initializer allows you to create runtime metadata for any Swift type, - /// which can then be used for type introspection and comparison. - /// - /// let intMetadata = Metadata(Int.self) - /// let stringMetadata = Metadata(String.self) - /// /// - Parameter type: The Swift type to create metadata for public init(_ type: any Any.Type) { self.init(rawValue: unsafeBitCast(type, to: UnsafePointer<_Metadata>.self)) } /// The Swift type represented by this metadata. - /// - /// This property allows you to convert from runtime metadata back to a Swift type, - /// enabling dynamic type operations. - /// - /// let metadata = Metadata(String.self) - /// let type = metadata.type // Returns String.Type public var type: any Any.Type { unsafeBitCast(rawValue, to: Any.Type.self) } From 6031a3a5fef6456840968da05b6cc65739f5e70c Mon Sep 17 00:00:00 2001 From: Kyle Date: Sat, 6 Sep 2025 23:53:37 +0800 Subject: [PATCH 08/12] Add comprehensive DocC documentation for Swift APIs Extension files created: - StatefulRule.md - Stateful computed attributes with mutable state - WeakAttribute.md - Weak reference attributes preventing retain cycles - Graph.md - Central dependency coordinator and update management - Subgraph.md - Scoped computation contexts for isolation - RuleContext.md - Rule evaluation context and input access - Focus.md - KeyPath-based property focusing rules Source documentation added: - StatefulRule.swift - Brief protocol description - WeakAttribute.swift - Weak reference property wrapper docs - OptionalAttribute.swift - Optional attribute wrapper docs - Focus.swift - KeyPath focusing rule docs - RuleContext.swift - Evaluation context docs - CompareValues.swift - Value comparison function docs All APIs now have proper DocC documentation following OpenSwiftUI patterns --- .spi.yml | 3 +- .../Optional/OptionalAttribute.swift | 1 + .../Attribute/Rule/Focus.swift | 1 + .../Attribute/Rule/StatefulRule.swift | 1 + .../Attribute/RuleContext/RuleContext.swift | 1 + .../Attribute/Weak/WeakAttribute.swift | 1 + .../OpenAttributeGraph.docc/Focus.md | 49 +++++++++++++++ .../OpenAttributeGraph.docc/Graph.md | 60 +++++++++++++++++++ .../OpenAttributeGraph.docc/RuleContext.md | 55 +++++++++++++++++ .../OpenAttributeGraph.docc/StatefulRule.md | 52 ++++++++++++++++ .../OpenAttributeGraph.docc/Subgraph.md | 48 +++++++++++++++ .../OpenAttributeGraph.docc/WeakAttribute.md | 55 +++++++++++++++++ .../Runtime/CompareValues.swift | 2 + 13 files changed, 327 insertions(+), 2 deletions(-) create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Focus.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/RuleContext.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/StatefulRule.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Subgraph.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/WeakAttribute.md diff --git a/.spi.yml b/.spi.yml index 5793db38..11024e65 100644 --- a/.spi.yml +++ b/.spi.yml @@ -1,5 +1,4 @@ version: 1 builder: configs: - - swift_version: 6.0 - documentation_targets: [OpenAttributeGraph] + - documentation_targets: [OpenAttributeGraph] diff --git a/Sources/OpenAttributeGraph/Attribute/Optional/OptionalAttribute.swift b/Sources/OpenAttributeGraph/Attribute/Optional/OptionalAttribute.swift index 9722b8ca..104bc653 100644 --- a/Sources/OpenAttributeGraph/Attribute/Optional/OptionalAttribute.swift +++ b/Sources/OpenAttributeGraph/Attribute/Optional/OptionalAttribute.swift @@ -5,6 +5,7 @@ // Audited for RELEASE_2021 // Status: Complete +/// An optional attribute wrapper that may or may not contain a value. @frozen @propertyWrapper @dynamicMemberLookup diff --git a/Sources/OpenAttributeGraph/Attribute/Rule/Focus.swift b/Sources/OpenAttributeGraph/Attribute/Rule/Focus.swift index dd23ab5a..c7c5e67d 100644 --- a/Sources/OpenAttributeGraph/Attribute/Rule/Focus.swift +++ b/Sources/OpenAttributeGraph/Attribute/Rule/Focus.swift @@ -5,6 +5,7 @@ // Audited for RELEASE_2021 // Status: Complete +/// A rule that focuses on a specific property of another attribute using KeyPath. @frozen public struct Focus: Rule, CustomStringConvertible { public var root: Attribute diff --git a/Sources/OpenAttributeGraph/Attribute/Rule/StatefulRule.swift b/Sources/OpenAttributeGraph/Attribute/Rule/StatefulRule.swift index be1894d4..e4a96c64 100644 --- a/Sources/OpenAttributeGraph/Attribute/Rule/StatefulRule.swift +++ b/Sources/OpenAttributeGraph/Attribute/Rule/StatefulRule.swift @@ -7,6 +7,7 @@ public import OpenAttributeGraphCxx +/// A protocol for defining computed attributes that maintain state between evaluations. public protocol StatefulRule: _AttributeBody { associatedtype Value static var initialValue: Value? { get } diff --git a/Sources/OpenAttributeGraph/Attribute/RuleContext/RuleContext.swift b/Sources/OpenAttributeGraph/Attribute/RuleContext/RuleContext.swift index 126b494c..2343107a 100644 --- a/Sources/OpenAttributeGraph/Attribute/RuleContext/RuleContext.swift +++ b/Sources/OpenAttributeGraph/Attribute/RuleContext/RuleContext.swift @@ -7,6 +7,7 @@ public import OpenAttributeGraphCxx +/// Context object providing access to rule evaluation state and input values. @frozen public struct RuleContext: Equatable { public var attribute: Attribute diff --git a/Sources/OpenAttributeGraph/Attribute/Weak/WeakAttribute.swift b/Sources/OpenAttributeGraph/Attribute/Weak/WeakAttribute.swift index 31341d90..3a2d9161 100644 --- a/Sources/OpenAttributeGraph/Attribute/Weak/WeakAttribute.swift +++ b/Sources/OpenAttributeGraph/Attribute/Weak/WeakAttribute.swift @@ -7,6 +7,7 @@ public import OpenAttributeGraphCxx +/// A weak reference property wrapper for attributes that prevents retain cycles. @frozen @propertyWrapper @dynamicMemberLookup diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Focus.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Focus.md new file mode 100644 index 00000000..6c51b370 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Focus.md @@ -0,0 +1,49 @@ +# ``Focus`` + +A rule that focuses on a specific property of another attribute using KeyPath. + +## Overview + +`Focus` provides a way to create attributes that automatically track a specific property of another attribute. It uses Swift's KeyPath system to create a focused view of part of a larger data structure. + + struct Person { + let name: String + let age: Int + } + + @Attribute var person = Person(name: "Alice", age: 30) + let nameAttribute = Attribute(Focus(root: $person, keyPath: \.name)) + // nameAttribute automatically updates when person.name changes + +Focus is commonly used internally by OpenAttributeGraph's dynamic member lookup system to create property-specific attributes. + +## Key Features + +- KeyPath-based focusing: Use any Swift KeyPath to focus on specific properties +- Automatic updates: Changes to the focused property automatically propagate +- Type safety: Full compile-time type checking for focused properties +- Efficient tracking: Only tracks changes to the specific focused property + +## Usage Pattern + +Focus is ideal for: +- Creating focused views of complex data structures +- Implementing dynamic member lookup for attributes +- Breaking down large objects into smaller, more manageable attribute pieces +- Selective observation of specific properties + +## Topics + +### Creating Focus Rules + +- ``init(root:keyPath:)`` + +### Properties + +- ``root`` +- ``keyPath`` +- ``value`` + +### Configuration + +- ``flags`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph.md new file mode 100644 index 00000000..15a7421f --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph.md @@ -0,0 +1,60 @@ +# ``Graph`` + +The central coordinator for attribute relationships and update cycles. + +## Overview + +`Graph` manages the dependency network between attributes and orchestrates efficient updates across the entire reactive system. It maintains a directed acyclic graph (DAG) of attribute dependencies and handles the propagation of changes. + +The graph automatically tracks dependencies when attributes are accessed during rule evaluation, detects cycles, and batches updates for optimal performance. + +## Key Features + +- Dependency tracking: Automatically discovers and maintains attribute relationships +- Cycle detection: Prevents and detects circular dependencies +- Batch updates: Groups multiple changes for efficient processing +- Update scheduling: Coordinates when and how attributes are recomputed +- Performance monitoring: Profiling and debugging capabilities + +## Update Propagation + +When an attribute changes, the graph efficiently propagates updates through three phases: +1. Mark phase: Changed attributes are marked as invalid +2. Sweep phase: Dependent attributes are transitively marked +3. Update phase: Values are recomputed in dependency order + +## Topics + +### Update Control + +- ``withoutUpdate(_:)`` +- ``withoutSubgraphInvalidation(_:)`` +- ``withDeadline(_:_:)`` + +### Callbacks + +- ``onInvalidation(_:)`` +- ``onUpdate(_:)`` + +### Performance Monitoring + +- ``startProfiling()`` +- ``stopProfiling()`` +- ``resetProfile()`` + +### Statistics + +- ``mainUpdates`` + +### Global Operations + +- ``anyInputsChanged(excluding:)`` + +### Output Management + +- ``outputValue()`` +- ``setOutputValue(_:)`` + +### Archive and Debug + +- ``archiveJSON(name:)`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/RuleContext.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/RuleContext.md new file mode 100644 index 00000000..ab6a106a --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/RuleContext.md @@ -0,0 +1,55 @@ +# ``RuleContext`` + +Context object providing access to rule evaluation state and input values. + +## Overview + +`RuleContext` provides a structured way to access input values and manage state during rule evaluation. It offers type-safe access to dependent attributes and their values within the context of a specific rule execution. + +The context ensures that dependency tracking is properly maintained while providing convenient access to input attributes. + +## Key Features + +- Type-safe input access: Access dependent attribute values with full type safety +- Dependency tracking: Automatically tracks accessed attributes as dependencies +- Value management: Direct access to current and changed values +- Context isolation: Maintains evaluation context for proper dependency resolution + +## Usage in Rules + +RuleContext is typically used within ``StatefulRule`` implementations to access dependencies and manage the rule's output value: + + struct MyRule: StatefulRule { + let inputAttribute: Attribute + + mutating func updateValue() { + let inputValue = context[inputAttribute] + value = inputValue * 2 + } + } + +## Topics + +### Creating Context + +- ``init(attribute:)`` + +### Input Access + +- ``subscript(_:)-1g3wa`` +- ``subscript(_:)-6y4wa`` +- ``subscript(_:)-2h8nh`` + +### Value Management + +- ``value`` +- ``hasValue`` + +### Change Tracking + +- ``changedValueFlagged(options:)`` +- ``wasModified(options:)`` + +### Associated Attribute + +- ``attribute`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/StatefulRule.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/StatefulRule.md new file mode 100644 index 00000000..2ff53ef6 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/StatefulRule.md @@ -0,0 +1,52 @@ +# ``StatefulRule`` + +A protocol for defining computed attributes that maintain state between evaluations. + +## Overview + +`StatefulRule` extends the basic `Rule` concept by allowing rules to maintain mutable state between updates. This is useful for rules that need to track changes over time or maintain internal state. + + struct CounterRule: StatefulRule { + typealias Value = Int + private var counter = 0 + + mutating func updateValue() { + counter += 1 + value = counter + } + } + +Unlike ``Rule``, `StatefulRule` allows mutation through the `updateValue()` method and provides direct access to the current value through the `value` property. + +## Key Features + +- Mutable state: Rules can maintain and modify internal state +- Direct value access: Read and write the current value directly +- Context access: Access to rule evaluation context and attribute +- Lifecycle control: Manual control over when and how values update + +## Usage Pattern + +StatefulRule is ideal for scenarios where you need to: +- Accumulate values over time +- Maintain counters or timers +- Implement complex state machines +- Cache expensive computations with custom invalidation + +## Topics + +### Protocol Requirements + +- ``Value`` +- ``initialValue`` +- ``updateValue()`` + +### Value Management + +- ``value`` +- ``hasValue`` + +### Context Access + +- ``attribute`` +- ``context`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Subgraph.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Subgraph.md new file mode 100644 index 00000000..a371e3e4 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Subgraph.md @@ -0,0 +1,48 @@ +# ``Subgraph`` + +Scoped computation contexts for isolated attribute groups. + +## Overview + +`Subgraph` provides scoped computation contexts that allow for isolated attribute groups with separate update domains. This enables better performance by reducing the scope of updates and provides isolated environments for testing. + +Subgraphs are essential for organizing complex attribute hierarchies and controlling the scope of reactive updates. + +## Key Features + +- Isolation: Separate update domains for different parts of your application +- Performance: Smaller update scopes reduce computational overhead +- Testing: Isolated environments for unit testing +- Observer pattern: Add observers for subgraph changes + +## Usage Pattern + +Subgraphs are commonly used to: +- Isolate different UI components or modules +- Create test environments with controlled attribute scopes +- Optimize performance by limiting update propagation +- Implement hierarchical reactive systems + +## Topics + +### Type Aliases + +- ``Flags`` +- ``ChildFlags`` + +### Observers + +- ``addObserver(_:)`` + +### Scoped Execution + +- ``apply(_:)`` + +### Attribute Iteration + +- ``forEach(_:_:)`` + +### Global Access + +- ``current`` +- ``currentGraphContext`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/WeakAttribute.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/WeakAttribute.md new file mode 100644 index 00000000..a6d5cc22 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/WeakAttribute.md @@ -0,0 +1,55 @@ +# ``WeakAttribute`` + +A weak reference property wrapper for attributes that prevents retain cycles. + +## Overview + +`WeakAttribute` provides a way to hold weak references to attributes, preventing strong reference cycles in the attribute graph while still allowing access to reactive values. + + @WeakAttribute var parentAttribute: SomeType? + + // Safe access to potentially deallocated attribute + if let value = parentAttribute { + print("Parent value: \(value)") + } + +The weak attribute automatically becomes `nil` when the referenced attribute is deallocated, providing memory-safe access to optional attribute references. + +## Key Features + +- Weak references: Prevents retain cycles in attribute relationships +- Automatic nil assignment: Referenced attributes become nil when deallocated +- Dynamic member lookup: Access nested properties through weak references +- Optional semantics: All values are optional since references may be deallocated + +## Usage Pattern + +WeakAttribute is essential for: +- Parent-child attribute relationships +- Observer patterns that don't own the observed attribute +- Breaking potential retain cycles in complex attribute graphs +- Optional attribute references in data structures + +## Topics + +### Creating Weak Attributes + +- ``init()`` +- ``init(base:)`` +- ``init(_:)-4u8wa`` +- ``init(_:)-571kb`` + +### Property Wrapper + +- ``wrappedValue`` +- ``projectedValue`` + +### Dynamic Member Access + +- ``subscript(dynamicMember:)`` + +### Value Access + +- ``attribute`` +- ``value`` +- ``changedValue(options:)`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/Runtime/CompareValues.swift b/Sources/OpenAttributeGraph/Runtime/CompareValues.swift index 7f9677af..9284ed77 100644 --- a/Sources/OpenAttributeGraph/Runtime/CompareValues.swift +++ b/Sources/OpenAttributeGraph/Runtime/CompareValues.swift @@ -15,10 +15,12 @@ private func OAGCompareValues( options: ComparisonOptions ) -> Bool +/// Compares two values using the specified comparison mode. public func compareValues(_ lhs: Value, _ rhs: Value, mode: ComparisonMode = .equatableAlways) -> Bool { compareValues(lhs, rhs, options: [.init(mode: mode), .copyOnWrite]) } +/// Compares two values using the specified comparison options. public func compareValues(_ lhs: Value, _ rhs: Value, options: ComparisonOptions) -> Bool { withUnsafePointer(to: lhs) { p1 in withUnsafePointer(to: rhs) { p2 in From e1cd7f5b365022c3d517823fe638f3b713dddadf Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 7 Sep 2025 00:13:39 +0800 Subject: [PATCH 09/12] Reorganize DocC extension files to match source structure - Create directory structure matching Sources layout: * Attribute/Attribute/ - Core attribute types * Attribute/Rule/ - Rule-based computed attributes * Attribute/Weak/ - Weak reference attributes * Attribute/Optional/ - Optional attribute wrappers * Attribute/RuleContext/ - Rule evaluation contexts * Graph/ - Graph management types * Runtime/ - Runtime introspection utilities - Move extension files to proper locations: * Attribute.md -> Attribute/Attribute/Attribute.md * Rule.md -> Attribute/Rule/Rule.md * StatefulRule.md -> Attribute/Rule/StatefulRule.md * Focus.md -> Attribute/Rule/Focus.md * WeakAttribute.md -> Attribute/Weak/WeakAttribute.md * RuleContext.md -> Attribute/RuleContext/RuleContext.md * Graph.md -> Graph/Graph.md * Subgraph.md -> Graph/Subgraph.md * Metadata.md -> Runtime/Metadata.md - Add OptionalAttribute.md documentation This organization improves documentation discoverability and maintains consistency with the source code structure. --- .../{ => Attribute/Attribute}/Attribute.md | 0 .../Attribute/Optional/OptionalAttribute.md | 59 +++++++++++++++++++ .../{ => Attribute/Rule}/Focus.md | 4 +- .../{ => Attribute/Rule}/Rule.md | 0 .../{ => Attribute/Rule}/StatefulRule.md | 0 .../RuleContext}/RuleContext.md | 0 .../{ => Attribute/Weak}/WeakAttribute.md | 0 .../{ => Graph}/Graph.md | 0 .../{ => Graph}/Subgraph.md | 0 .../{ => Runtime}/Metadata.md | 0 10 files changed, 60 insertions(+), 3 deletions(-) rename Sources/OpenAttributeGraph/OpenAttributeGraph.docc/{ => Attribute/Attribute}/Attribute.md (100%) create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Optional/OptionalAttribute.md rename Sources/OpenAttributeGraph/OpenAttributeGraph.docc/{ => Attribute/Rule}/Focus.md (93%) rename Sources/OpenAttributeGraph/OpenAttributeGraph.docc/{ => Attribute/Rule}/Rule.md (100%) rename Sources/OpenAttributeGraph/OpenAttributeGraph.docc/{ => Attribute/Rule}/StatefulRule.md (100%) rename Sources/OpenAttributeGraph/OpenAttributeGraph.docc/{ => Attribute/RuleContext}/RuleContext.md (100%) rename Sources/OpenAttributeGraph/OpenAttributeGraph.docc/{ => Attribute/Weak}/WeakAttribute.md (100%) rename Sources/OpenAttributeGraph/OpenAttributeGraph.docc/{ => Graph}/Graph.md (100%) rename Sources/OpenAttributeGraph/OpenAttributeGraph.docc/{ => Graph}/Subgraph.md (100%) rename Sources/OpenAttributeGraph/OpenAttributeGraph.docc/{ => Runtime}/Metadata.md (100%) diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Attribute/Attribute.md similarity index 100% rename from Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute.md rename to Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Attribute/Attribute.md diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Optional/OptionalAttribute.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Optional/OptionalAttribute.md new file mode 100644 index 00000000..103efe57 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Optional/OptionalAttribute.md @@ -0,0 +1,59 @@ +# ``OptionalAttribute`` + +An optional attribute wrapper that may or may not contain a value. + +## Overview + +`OptionalAttribute` provides a way to work with attributes that may be nil, offering optional semantics for attribute references. This is useful when working with attributes that may be conditionally created or destroyed. + + @OptionalAttribute var maybeAttribute: Int? + + if let value = maybeAttribute { + print("Attribute value: \(value)") + } + +The optional attribute wrapper automatically handles the optional nature of attribute references while maintaining the reactive capabilities of the attribute system. + +## Key Features + +- Optional semantics: Natural handling of attributes that may not exist +- Conditional access: Safe access to potentially nil attributes +- Reactive updates: Changes propagate when the attribute becomes available +- Integration with weak attributes: Works seamlessly with ``WeakAttribute`` + +## Usage Pattern + +OptionalAttribute is commonly used for: +- Conditionally created UI elements +- Optional data model properties +- Weak attribute references that may become nil +- Lazy initialization scenarios + +## Topics + +### Creating Optional Attributes + +- ``init()`` +- ``init(base:)`` +- ``init(_:)-47ane`` +- ``init(_:)-9eqjv`` +- ``init(_:)-2u3gq`` + +### Property Wrapper + +- ``wrappedValue`` +- ``projectedValue`` + +### Value Access + +- ``attribute`` +- ``value`` +- ``changedValue(options:)`` + +### Transformations + +- ``map(_:)`` + +### Base Access + +- ``base`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Focus.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/Focus.md similarity index 93% rename from Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Focus.md rename to Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/Focus.md index 6c51b370..b79b0bb6 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Focus.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/Focus.md @@ -1,7 +1,5 @@ # ``Focus`` -A rule that focuses on a specific property of another attribute using KeyPath. - ## Overview `Focus` provides a way to create attributes that automatically track a specific property of another attribute. It uses Swift's KeyPath system to create a focused view of part of a larger data structure. @@ -46,4 +44,4 @@ Focus is ideal for: ### Configuration -- ``flags`` \ No newline at end of file +- ``flags`` diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Rule.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/Rule.md similarity index 100% rename from Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Rule.md rename to Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/Rule.md diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/StatefulRule.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/StatefulRule.md similarity index 100% rename from Sources/OpenAttributeGraph/OpenAttributeGraph.docc/StatefulRule.md rename to Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/StatefulRule.md diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/RuleContext.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/RuleContext/RuleContext.md similarity index 100% rename from Sources/OpenAttributeGraph/OpenAttributeGraph.docc/RuleContext.md rename to Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/RuleContext/RuleContext.md diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/WeakAttribute.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Weak/WeakAttribute.md similarity index 100% rename from Sources/OpenAttributeGraph/OpenAttributeGraph.docc/WeakAttribute.md rename to Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Weak/WeakAttribute.md diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph/Graph.md similarity index 100% rename from Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph.md rename to Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph/Graph.md diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Subgraph.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph/Subgraph.md similarity index 100% rename from Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Subgraph.md rename to Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph/Subgraph.md diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Metadata.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/Metadata.md similarity index 100% rename from Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Metadata.md rename to Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/Metadata.md From f610f92ce81b38ea81fe22c222692d38ca59047c Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 7 Sep 2025 00:16:27 +0800 Subject: [PATCH 10/12] Move comprehensive documentation from extension files to Swift source - Move overview, examples, and usage patterns from DocC extension files to Swift source files - Keep only Topics sections in extension files for API organization - Updated source files with comprehensive documentation: * Attribute.swift - Full property wrapper documentation with examples * Rule.swift - Complete protocol documentation with usage patterns * StatefulRule.swift - Detailed stateful rule documentation * WeakAttribute.swift - Comprehensive weak reference documentation * Focus.swift - Complete KeyPath-based focusing documentation - Simplified extension files to contain only Topics sections: * Attribute.md - Topics organization only * Rule.md - Topics organization only * StatefulRule.md - Topics organization only * WeakAttribute.md - Topics organization only * Focus.md - Topics organization only This provides comprehensive in-source documentation while maintaining clean Topics-based API organization in extension files. --- .../Attribute/Attribute/Attribute.swift | 52 +++++++++++++++++ .../Attribute/Rule/Focus.swift | 28 ++++++++++ .../Attribute/Rule/Rule.swift | 38 +++++++++++++ .../Attribute/Rule/StatefulRule.swift | 29 ++++++++++ .../Attribute/Weak/WeakAttribute.swift | 26 +++++++++ .../Attribute/Attribute/Attribute.md | 56 ------------------- .../Attribute/Rule/Focus.md | 30 ---------- .../Attribute/Rule/Rule.md | 41 -------------- .../Attribute/Rule/StatefulRule.md | 33 ----------- .../Attribute/Weak/WeakAttribute.md | 30 ---------- 10 files changed, 173 insertions(+), 190 deletions(-) diff --git a/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift b/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift index 0425167a..a52f44be 100644 --- a/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift +++ b/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift @@ -1,6 +1,58 @@ public import OpenAttributeGraphCxx /// A reactive property wrapper that automatically tracks dependencies and manages value updates. +/// +/// `Attribute` is the core building block of the OpenAttributeGraph reactive system. When you wrap a property with `@Attribute`, it becomes reactive and can automatically track dependencies and propagate changes. +/// +/// @Attribute var count: Int = 0 +/// @Attribute var doubledCount: Int = count * 2 +/// +/// count = 5 // doubledCount automatically becomes 10 +/// +/// ## Key Features +/// +/// - Automatic dependency tracking: Attributes automatically discover their dependencies +/// - Efficient updates: Only affected attributes are recomputed when changes occur +/// - Type safety: Full Swift type safety with compile-time checking +/// - Dynamic member lookup: Access nested properties as reactive attributes +/// - Property wrapper syntax: Clean, declarative syntax using `@Attribute` +/// +/// ## Property Wrapper Usage +/// +/// Use `@Attribute` to make any Swift value reactive: +/// +/// struct CounterView { +/// @Attribute var count: Int = 0 +/// +/// var body: some View { +/// Button("Count: \(count)") { +/// count += 1 +/// } +/// } +/// } +/// +/// ## Dynamic Member Lookup +/// +/// Access nested properties as separate attributes: +/// +/// @Attribute var person: Person = Person(name: "Alice", age: 30) +/// let nameAttribute: Attribute = person.name +/// let ageAttribute: Attribute = person.age +/// +/// ## Integration with Rules +/// +/// Create computed attributes using ``Rule`` or ``StatefulRule``: +/// +/// struct DoubledRule: Rule { +/// typealias Value = Int +/// let source: Attribute +/// +/// func value() -> Int { +/// source.wrappedValue * 2 +/// } +/// } +/// +/// let doubled = Attribute(DoubledRule(source: count)) @frozen @propertyWrapper @dynamicMemberLookup diff --git a/Sources/OpenAttributeGraph/Attribute/Rule/Focus.swift b/Sources/OpenAttributeGraph/Attribute/Rule/Focus.swift index c7c5e67d..47a7c69a 100644 --- a/Sources/OpenAttributeGraph/Attribute/Rule/Focus.swift +++ b/Sources/OpenAttributeGraph/Attribute/Rule/Focus.swift @@ -6,6 +6,34 @@ // Status: Complete /// A rule that focuses on a specific property of another attribute using KeyPath. +/// +/// `Focus` provides a way to create attributes that automatically track a specific property of another attribute. It uses Swift's KeyPath system to create a focused view of part of a larger data structure. +/// +/// struct Person { +/// let name: String +/// let age: Int +/// } +/// +/// @Attribute var person = Person(name: "Alice", age: 30) +/// let nameAttribute = Attribute(Focus(root: $person, keyPath: \.name)) +/// // nameAttribute automatically updates when person.name changes +/// +/// Focus is commonly used internally by OpenAttributeGraph's dynamic member lookup system to create property-specific attributes. +/// +/// ## Key Features +/// +/// - KeyPath-based focusing: Use any Swift KeyPath to focus on specific properties +/// - Automatic updates: Changes to the focused property automatically propagate +/// - Type safety: Full compile-time type checking for focused properties +/// - Efficient tracking: Only tracks changes to the specific focused property +/// +/// ## Usage Pattern +/// +/// Focus is ideal for: +/// - Creating focused views of complex data structures +/// - Implementing dynamic member lookup for attributes +/// - Breaking down large objects into smaller, more manageable attribute pieces +/// - Selective observation of specific properties @frozen public struct Focus: Rule, CustomStringConvertible { public var root: Attribute diff --git a/Sources/OpenAttributeGraph/Attribute/Rule/Rule.swift b/Sources/OpenAttributeGraph/Attribute/Rule/Rule.swift index cf9295b9..4cdfa84d 100644 --- a/Sources/OpenAttributeGraph/Attribute/Rule/Rule.swift +++ b/Sources/OpenAttributeGraph/Attribute/Rule/Rule.swift @@ -8,6 +8,44 @@ public import OpenAttributeGraphCxx /// A protocol for defining computed attributes that automatically update when dependencies change. +/// +/// Rules provide a way to create derived attributes that compute their values based on other attributes. +/// When any dependency changes, the rule will automatically recompute its value. +/// +/// struct DoubledRule: Rule { +/// typealias Value = Int +/// let source: Attribute +/// +/// var value: Int { +/// source.wrappedValue * 2 +/// } +/// } +/// +/// @Attribute var count: Int = 5 +/// let doubled = Attribute(DoubledRule(source: $count)) +/// // doubled.wrappedValue == 10 +/// +/// count = 10 +/// // doubled.wrappedValue automatically becomes 20 +/// +/// ## Key Features +/// +/// - Automatic dependency tracking: Dependencies are discovered automatically when accessed +/// - Lazy evaluation: Values are only computed when needed +/// - Caching: Results are cached until dependencies change +/// - Efficient updates: Only recomputes when dependencies actually change +/// +/// ## Implementation Requirements +/// +/// Types conforming to `Rule` must provide: +/// - `Value`: The type of value produced by the rule +/// - `value`: A computed property that returns the current value +/// - `initialValue`: An optional initial value (defaults to `nil`) +/// +/// ## Advanced Usage +/// +/// For rules that need to maintain state between evaluations, see ``StatefulRule``. +/// For rules that can be cached based on their content, make your rule type conform to `Hashable`. public protocol Rule: _AttributeBody { /// The type of value produced by this rule. associatedtype Value diff --git a/Sources/OpenAttributeGraph/Attribute/Rule/StatefulRule.swift b/Sources/OpenAttributeGraph/Attribute/Rule/StatefulRule.swift index e4a96c64..8ca72d46 100644 --- a/Sources/OpenAttributeGraph/Attribute/Rule/StatefulRule.swift +++ b/Sources/OpenAttributeGraph/Attribute/Rule/StatefulRule.swift @@ -8,6 +8,35 @@ public import OpenAttributeGraphCxx /// A protocol for defining computed attributes that maintain state between evaluations. +/// +/// `StatefulRule` extends the basic `Rule` concept by allowing rules to maintain mutable state between updates. This is useful for rules that need to track changes over time or maintain internal state. +/// +/// struct CounterRule: StatefulRule { +/// typealias Value = Int +/// private var counter = 0 +/// +/// mutating func updateValue() { +/// counter += 1 +/// value = counter +/// } +/// } +/// +/// Unlike ``Rule``, `StatefulRule` allows mutation through the `updateValue()` method and provides direct access to the current value through the `value` property. +/// +/// ## Key Features +/// +/// - Mutable state: Rules can maintain and modify internal state +/// - Direct value access: Read and write the current value directly +/// - Context access: Access to rule evaluation context and attribute +/// - Lifecycle control: Manual control over when and how values update +/// +/// ## Usage Pattern +/// +/// StatefulRule is ideal for scenarios where you need to: +/// - Accumulate values over time +/// - Maintain counters or timers +/// - Implement complex state machines +/// - Cache expensive computations with custom invalidation public protocol StatefulRule: _AttributeBody { associatedtype Value static var initialValue: Value? { get } diff --git a/Sources/OpenAttributeGraph/Attribute/Weak/WeakAttribute.swift b/Sources/OpenAttributeGraph/Attribute/Weak/WeakAttribute.swift index 3a2d9161..2fa4f975 100644 --- a/Sources/OpenAttributeGraph/Attribute/Weak/WeakAttribute.swift +++ b/Sources/OpenAttributeGraph/Attribute/Weak/WeakAttribute.swift @@ -8,6 +8,32 @@ public import OpenAttributeGraphCxx /// A weak reference property wrapper for attributes that prevents retain cycles. +/// +/// `WeakAttribute` provides a way to hold weak references to attributes, preventing strong reference cycles in the attribute graph while still allowing access to reactive values. +/// +/// @WeakAttribute var parentAttribute: SomeType? +/// +/// // Safe access to potentially deallocated attribute +/// if let value = parentAttribute { +/// print("Parent value: \(value)") +/// } +/// +/// The weak attribute automatically becomes `nil` when the referenced attribute is deallocated, providing memory-safe access to optional attribute references. +/// +/// ## Key Features +/// +/// - Weak references: Prevents retain cycles in attribute relationships +/// - Automatic nil assignment: Referenced attributes become nil when deallocated +/// - Dynamic member lookup: Access nested properties through weak references +/// - Optional semantics: All values are optional since references may be deallocated +/// +/// ## Usage Pattern +/// +/// WeakAttribute is essential for: +/// - Parent-child attribute relationships +/// - Observer patterns that don't own the observed attribute +/// - Breaking potential retain cycles in complex attribute graphs +/// - Optional attribute references in data structures @frozen @propertyWrapper @dynamicMemberLookup diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Attribute/Attribute.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Attribute/Attribute.md index ae762a21..a255efa8 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Attribute/Attribute.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Attribute/Attribute.md @@ -1,61 +1,5 @@ # ``Attribute`` -A reactive property wrapper that automatically tracks dependencies and manages value updates. - -## Overview - -`Attribute` is the core building block of the OpenAttributeGraph reactive system. When you wrap a property with `@Attribute`, it becomes reactive and can automatically track dependencies and propagate changes. - - @Attribute var count: Int = 0 - @Attribute var doubledCount: Int = count * 2 - - count = 5 // doubledCount automatically becomes 10 - -## Key Features - -- Automatic dependency tracking: Attributes automatically discover their dependencies -- Efficient updates: Only affected attributes are recomputed when changes occur -- Type safety: Full Swift type safety with compile-time checking -- Dynamic member lookup: Access nested properties as reactive attributes -- Property wrapper syntax: Clean, declarative syntax using `@Attribute` - -## Property Wrapper Usage - -Use `@Attribute` to make any Swift value reactive: - - struct CounterView { - @Attribute var count: Int = 0 - - var body: some View { - Button("Count: \(count)") { - count += 1 - } - } - } - -## Dynamic Member Lookup - -Access nested properties as separate attributes: - - @Attribute var person: Person = Person(name: "Alice", age: 30) - let nameAttribute: Attribute = person.name - let ageAttribute: Attribute = person.age - -## Integration with Rules - -Create computed attributes using ``Rule`` or ``StatefulRule``: - - struct DoubledRule: Rule { - typealias Value = Int - let source: Attribute - - func value() -> Int { - source.wrappedValue * 2 - } - } - - let doubled = Attribute(DoubledRule(source: count)) - ## Topics ### Creating Attributes diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/Focus.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/Focus.md index b79b0bb6..54a8c9c2 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/Focus.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/Focus.md @@ -1,35 +1,5 @@ # ``Focus`` -## Overview - -`Focus` provides a way to create attributes that automatically track a specific property of another attribute. It uses Swift's KeyPath system to create a focused view of part of a larger data structure. - - struct Person { - let name: String - let age: Int - } - - @Attribute var person = Person(name: "Alice", age: 30) - let nameAttribute = Attribute(Focus(root: $person, keyPath: \.name)) - // nameAttribute automatically updates when person.name changes - -Focus is commonly used internally by OpenAttributeGraph's dynamic member lookup system to create property-specific attributes. - -## Key Features - -- KeyPath-based focusing: Use any Swift KeyPath to focus on specific properties -- Automatic updates: Changes to the focused property automatically propagate -- Type safety: Full compile-time type checking for focused properties -- Efficient tracking: Only tracks changes to the specific focused property - -## Usage Pattern - -Focus is ideal for: -- Creating focused views of complex data structures -- Implementing dynamic member lookup for attributes -- Breaking down large objects into smaller, more manageable attribute pieces -- Selective observation of specific properties - ## Topics ### Creating Focus Rules diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/Rule.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/Rule.md index f639ca70..faea4b64 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/Rule.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/Rule.md @@ -1,46 +1,5 @@ # ``Rule`` -A protocol for defining computed attributes that automatically update when dependencies change. - -## Overview - -Rules provide a way to create derived attributes that compute their values based on other attributes. When any dependency changes, the rule will automatically recompute its value. - - struct DoubledRule: Rule { - typealias Value = Int - let source: Attribute - - var value: Int { - source.wrappedValue * 2 - } - } - - @Attribute var count: Int = 5 - let doubled = Attribute(DoubledRule(source: $count)) - // doubled.wrappedValue == 10 - - count = 10 - // doubled.wrappedValue automatically becomes 20 - -## Key Features - -- Automatic dependency tracking: Dependencies are discovered automatically when accessed -- Lazy evaluation: Values are only computed when needed -- Caching: Results are cached until dependencies change -- Efficient updates: Only recomputes when dependencies actually change - -## Implementation Requirements - -Types conforming to `Rule` must provide: -- `Value`: The type of value produced by the rule -- `value`: A computed property that returns the current value -- `initialValue`: An optional initial value (defaults to `nil`) - -## Advanced Usage - -For rules that need to maintain state between evaluations, see ``StatefulRule``. -For rules that can be cached based on their content, make your rule type conform to `Hashable`. - ## Topics ### Protocol Requirements diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/StatefulRule.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/StatefulRule.md index 2ff53ef6..bea5345f 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/StatefulRule.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/StatefulRule.md @@ -1,38 +1,5 @@ # ``StatefulRule`` -A protocol for defining computed attributes that maintain state between evaluations. - -## Overview - -`StatefulRule` extends the basic `Rule` concept by allowing rules to maintain mutable state between updates. This is useful for rules that need to track changes over time or maintain internal state. - - struct CounterRule: StatefulRule { - typealias Value = Int - private var counter = 0 - - mutating func updateValue() { - counter += 1 - value = counter - } - } - -Unlike ``Rule``, `StatefulRule` allows mutation through the `updateValue()` method and provides direct access to the current value through the `value` property. - -## Key Features - -- Mutable state: Rules can maintain and modify internal state -- Direct value access: Read and write the current value directly -- Context access: Access to rule evaluation context and attribute -- Lifecycle control: Manual control over when and how values update - -## Usage Pattern - -StatefulRule is ideal for scenarios where you need to: -- Accumulate values over time -- Maintain counters or timers -- Implement complex state machines -- Cache expensive computations with custom invalidation - ## Topics ### Protocol Requirements diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Weak/WeakAttribute.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Weak/WeakAttribute.md index a6d5cc22..521c8209 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Weak/WeakAttribute.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Weak/WeakAttribute.md @@ -1,35 +1,5 @@ # ``WeakAttribute`` -A weak reference property wrapper for attributes that prevents retain cycles. - -## Overview - -`WeakAttribute` provides a way to hold weak references to attributes, preventing strong reference cycles in the attribute graph while still allowing access to reactive values. - - @WeakAttribute var parentAttribute: SomeType? - - // Safe access to potentially deallocated attribute - if let value = parentAttribute { - print("Parent value: \(value)") - } - -The weak attribute automatically becomes `nil` when the referenced attribute is deallocated, providing memory-safe access to optional attribute references. - -## Key Features - -- Weak references: Prevents retain cycles in attribute relationships -- Automatic nil assignment: Referenced attributes become nil when deallocated -- Dynamic member lookup: Access nested properties through weak references -- Optional semantics: All values are optional since references may be deallocated - -## Usage Pattern - -WeakAttribute is essential for: -- Parent-child attribute relationships -- Observer patterns that don't own the observed attribute -- Breaking potential retain cycles in complex attribute graphs -- Optional attribute references in data structures - ## Topics ### Creating Weak Attributes From a543e2c31184481abe6fcfdea60fd3c027eadf6b Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 7 Sep 2025 00:38:30 +0800 Subject: [PATCH 11/12] Update documentation --- README.md | 37 ++------------ .../Attribute/Attribute/Attribute.swift | 4 +- .../OpenAttributeGraph.docc/AdvancedTopics.md | 28 ----------- .../Attribute/Attribute-References.md | 45 +++++++++++++++++ .../Attribute/Computed-Attributes.md | 43 ++++++++++++++++ .../Attribute/Reactive-Attributes.md | 36 +++++++++++++ .../OpenAttributeGraph.docc/CoreComponents.md | 49 ------------------ .../Graph/Dependency-Graphs.md | 50 +++++++++++++++++++ .../OpenAttributeGraph.md | 14 ++++-- .../Runtime/Type-Introspection.md | 38 ++++++++++++++ 10 files changed, 229 insertions(+), 115 deletions(-) delete mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/AdvancedTopics.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Attribute-References.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Computed-Attributes.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Reactive-Attributes.md delete mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/CoreComponents.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph/Dependency-Graphs.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/Type-Introspection.md diff --git a/README.md b/README.md index ebb8b59d..e1abf2b9 100644 --- a/README.md +++ b/README.md @@ -6,40 +6,9 @@ [![codecov](https://codecov.io/gh/OpenSwiftUIProject/OpenAttributeGraph/graph/badge.svg?token=W1KDSUMWJW)](https://codecov.io/gh/OpenSwiftUIProject/OpenAttributeGraph) -OpenAttributeGraph is an open source implementation of Apple's Private framework - AttributeGraph +OpenAttributeGraph is an open source implementation of Apple's Private framework - AttributeGraph which is a high performance computing engine written in C++ and Swift. -AttributeGraph is a high performance computing engine written in C++ and Swift. - -And it powers the underlying computing and diffing of SwiftUI. - -## Architecture - -OpenAttributeGraph consists of three main components: - -### Attribute Part -The **Attribute** system provides a reactive property wrapper that automatically tracks dependencies and manages value updates. Key features include: -- `Attribute` - A property wrapper for reactive values with automatic dependency tracking -- `AnyAttribute` - Type-erased attribute for runtime flexibility -- **Rules** - Transform attributes through `Rule` and `StatefulRule` protocols -- **Weak/Optional** - Support for optional and weak attribute references -- **Body system** - Efficient value computation and caching mechanisms - -### Graph Part -The **Graph** manages the dependency network and orchestrates updates across attributes. Core functionality includes: -- `Graph` - Central coordinator for attribute relationships and update cycles -- `Subgraph` - Scoped computation contexts for isolated attribute groups -- **Invalidation tracking** - Efficient change propagation through the dependency graph -- **Update scheduling** - Optimized batch processing of attribute changes -- **Profiling support** - Performance monitoring and debugging capabilities - -### Runtime Part -The **Runtime** provides low-level type introspection and memory management utilities. This includes: -- `Metadata` - Swift runtime type information and reflection capabilities -- **Type comparison** - Efficient value equality checking across different types -- **Memory layout** - Safe pointer manipulation and offset calculations -- **Tuple handling** - Runtime support for tuple types and field access - -> **Note**: The Runtime part leverages techniques similar to those found in [wickwirew/Runtime](https://github.com/wickwirew/Runtime) for Swift runtime introspection. +And it powers the underlying computing and diffing of [OpenSwiftUI](https://github.com/OpenSwiftUIProject/OpenSwiftUI). | **CI Status** | |---| @@ -54,6 +23,8 @@ The project is for the following purposes: Currently, this project is in early development. +Please refer to the [documentation](https://swiftpackageindex.com/OpenSwiftUIProject/OpenAttributeGraph/main/documentation/openattributegraph) for more information on it. + ## Usage ### Via Swift Package Manager diff --git a/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift b/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift index a52f44be..716eb10b 100644 --- a/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift +++ b/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift @@ -2,7 +2,9 @@ public import OpenAttributeGraphCxx /// A reactive property wrapper that automatically tracks dependencies and manages value updates. /// -/// `Attribute` is the core building block of the OpenAttributeGraph reactive system. When you wrap a property with `@Attribute`, it becomes reactive and can automatically track dependencies and propagate changes. +/// `Attribute` is the core building block of the OpenAttributeGraph reactive system. When you wrap a +/// property with `@Attribute`, it becomes reactive and can automatically track dependencies and +/// propagate changes. /// /// @Attribute var count: Int = 0 /// @Attribute var doubledCount: Int = count * 2 diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/AdvancedTopics.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/AdvancedTopics.md deleted file mode 100644 index 0d9a4592..00000000 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/AdvancedTopics.md +++ /dev/null @@ -1,28 +0,0 @@ -# AdvancedTopics - -Advanced features and implementation details for sophisticated use cases. - -## Overview - -These advanced topics cover specialized functionality and implementation details that are useful for complex scenarios and deep integration with OpenAttributeGraph's reactive system. - -## Attribute Bodies - -Low-level attribute implementation and visitor patterns for advanced attribute manipulation. - -- ``AttributeBodyVisitor`` - Protocol for visiting and inspecting attribute bodies -- ``ObservedAttribute`` - Attribute wrapper for observing changes in other attributes - -## Context Management - -Types for managing evaluation contexts and rule execution environments. - -- ``RuleContext`` - Context object providing access to rule evaluation state -- ``AnyRuleContext`` - Type-erased rule context for runtime flexibility - -## Type System Support - -Utilities for working with external values and memory layout manipulation. - -- ``External`` - Wrapper for external values not managed by the attribute graph -- ``PointerOffset`` - Type-safe pointer arithmetic for nested attribute access \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Attribute-References.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Attribute-References.md new file mode 100644 index 00000000..4e974bd4 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Attribute-References.md @@ -0,0 +1,45 @@ +# Attribute References + +Type-erased and reference management for attributes. + +## Overview + +Attribute references provide type-erased access to attributes and specialized reference management for memory-sensitive scenarios. The AnyAttribute type allows working with attributes without knowing their specific value types, while reference-based attributes provide different memory management strategies. + +These reference types are essential for building flexible reactive systems where attribute types may not be known at compile time, or where careful memory management is required to avoid retain cycles. + +## Topics + +### Type-Erased References + +- ``AnyAttribute`` + +### Reference Creation + +- ``AnyAttribute/init(_:)`` +- ``Attribute/init(identifier:)`` + +### Reference Operations + +- ``AnyAttribute/unsafeCast(to:)`` +- ``Attribute/unsafeCast(to:)`` +- ``AnyAttribute/create(offset:size:)`` + +### Reference Properties + +- ``AnyAttribute/identifier`` +- ``Attribute/identifier`` + +### Memory Management + +- ``AnyAttribute/graph`` +- ``AnyAttribute/subgraph`` +- ``Attribute/graph`` +- ``Attribute/subgraph`` + +### Value State + +- ``AnyAttribute/valueState`` +- ``Attribute/valueState`` +- ``AnyAttribute/hasValue`` +- ``Attribute/hasValue`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Computed-Attributes.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Computed-Attributes.md new file mode 100644 index 00000000..53b4dea0 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Computed-Attributes.md @@ -0,0 +1,43 @@ +# Computed Attributes + +Rule-based attributes that compute their values from other attributes. + +## Overview + +Computed attributes provide a declarative way to create attributes whose values are derived from other attributes. They use rule-based computation to automatically recalculate their values when dependencies change, forming the backbone of OpenAttributeGraph's reactive computation system. + +Rules can be stateless for simple computations or stateful when they need to maintain internal state across updates. The Focus rule provides a specialized way to create attributes that track specific properties of other attributes using Swift's KeyPath system. + +## Topics + +### Rule Protocols + +- ``Rule`` +- ``StatefulRule`` +- ``_AttributeBody`` + +### Specialized Rules + +- ``Focus`` +- ``External`` + +### Rule Creation + +- ``Attribute/init(_:)-4tj1v`` +- ``Attribute/init(_:)-8hz0z`` +- ``Focus/init(root:keyPath:)`` + +### Rule Properties + +- ``Rule/value`` +- ``Rule/flags`` +- ``StatefulRule/value`` +- ``StatefulRule/flags`` +- ``Focus/root`` +- ``Focus/keyPath`` +- ``Focus/value`` + +### Update Mechanisms + +- ``Rule/_update`` +- ``StatefulRule/_update`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Reactive-Attributes.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Reactive-Attributes.md new file mode 100644 index 00000000..d1372e09 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Reactive-Attributes.md @@ -0,0 +1,36 @@ +# Reactive Attributes + +Reactive properties that automatically track dependencies and manage value updates. + +## Overview + +Reactive attributes form the foundation of OpenAttributeGraph's reactive programming model. These attributes automatically track their dependencies and efficiently propagate changes through the dependency graph when their values change. + +The primary reactive attribute types provide different levels of memory management and reference semantics to handle various use cases in reactive applications. + +## Topics + +### Core Reactive Types + +- ``Attribute`` +- ``WeakAttribute`` +- ``OptionalAttribute`` + +### Property Wrapper Support + +- ``Attribute/wrappedValue`` +- ``Attribute/projectedValue`` +- ``WeakAttribute/wrappedValue`` +- ``WeakAttribute/projectedValue`` + +### Dynamic Member Access + +- ``Attribute/subscript(dynamicMember:)`` +- ``WeakAttribute/subscript(dynamicMember:)`` + +### Value Management + +- ``Attribute/value`` +- ``Attribute/setValue(_:)`` +- ``WeakAttribute/value`` +- ``WeakAttribute/changedValue(options:)`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/CoreComponents.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/CoreComponents.md deleted file mode 100644 index 261cb1ee..00000000 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/CoreComponents.md +++ /dev/null @@ -1,49 +0,0 @@ -# CoreComponents - -The fundamental building blocks of OpenAttributeGraph's reactive programming system. - -## Overview - -OpenAttributeGraph provides a comprehensive set of components for building reactive applications. These core components work together to provide automatic dependency tracking, efficient updates, and a clean programming model. - -## Attributes - -The foundation of the reactive system, providing property wrappers and type-erased access to reactive values. - -- ``Attribute`` - The primary property wrapper for reactive values -- ``AnyAttribute`` - Type-erased attribute for runtime flexibility -- ``WeakAttribute`` - Weak reference attribute wrapper -- ``AnyWeakAttribute`` - Type-erased weak attribute -- ``OptionalAttribute`` - Optional value attribute wrapper -- ``AnyOptionalAttribute`` - Type-erased optional attribute -- ``IndirectAttribute`` - Indirect attribute for complex reference scenarios - -## Rules and Transformations - -Protocols and types for creating computed attributes that derive their values from other attributes. - -- ``Rule`` - Protocol for stateless computed attributes -- ``StatefulRule`` - Protocol for stateful computed attributes -- ``Focus`` - Rule for focusing on part of an attribute's value -- ``Map`` - Rule for transforming attribute values - -## Graph Management - -Types that manage the dependency graph and coordinate updates across attributes. - -- ``Graph`` - Central coordinator for attribute relationships and updates -- ``Subgraph`` - Scoped computation context for isolated attribute groups - -## Runtime Support - -Low-level utilities for type introspection, comparison, and memory management. - -- ``Metadata`` - Swift runtime type information and reflection -- ``compareValues(_:_:mode:)`` - Efficient value comparison across types -- ``TupleType`` - Runtime support for tuple types and operations - -## Debugging and Development - -Tools for debugging attribute graphs and monitoring performance. - -- ``DebugServer`` - Server for debugging and introspecting attribute graphs \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph/Dependency-Graphs.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph/Dependency-Graphs.md new file mode 100644 index 00000000..3a2316be --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph/Dependency-Graphs.md @@ -0,0 +1,50 @@ +# Dependency Graphs + +Graph structures that manage attribute dependencies and updates. + +## Overview + +Dependency graphs form the backbone of OpenAttributeGraph's reactive system, managing relationships between attributes and coordinating updates when values change. The graph system uses a two-level hierarchy with global graphs containing multiple subgraphs for efficient organization and update propagation. + +Graphs automatically track dependencies as attributes access other attributes during computation, building an efficient dependency network that minimizes unnecessary recalculations when changes occur. + +## Topics + +### Graph Types + +- ``Graph`` +- ``Subgraph`` + +### Graph Creation + +- ``Graph/init()`` +- ``Subgraph/init()`` + +### Graph Management + +- ``Graph/typeIndex(ctx:body:valueType:flags:update:)`` +- ``Subgraph/currentGraphContext`` + +### Update Coordination + +- ``Graph/willInvalidate(attribute:)`` +- ``Graph/updateValue()`` +- ``Subgraph/update()`` + +### Graph Traversal + +- ``Attribute/breadthFirstSearch(options:_:)`` +- ``AnyAttribute/breadthFirstSearch(options:_:)`` + +### Input Management + +- ``Attribute/addInput(_:options:token:)`` +- ``Attribute/addInput(_:options:token:)-6p8bn`` +- ``AnyAttribute/addInput(_:options:token:)`` + +### Graph Properties + +- ``Attribute/graph`` +- ``Attribute/subgraph`` +- ``AnyAttribute/graph`` +- ``AnyAttribute/subgraph`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md index d889cd32..f8f0595e 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md @@ -14,10 +14,16 @@ The framework is designed for high performance and powers the reactive updates t - -### Core Components +### Attributes -- +- +- +- -### Advanced Topics +### Graph Management -- +- + +### Runtime Support + +- diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/Type-Introspection.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/Type-Introspection.md new file mode 100644 index 00000000..28491a19 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/Type-Introspection.md @@ -0,0 +1,38 @@ +# Type Introspection + +Runtime type information and introspection utilities. + +## Overview + +Type introspection provides runtime access to Swift type metadata, enabling OpenAttributeGraph to work with types dynamically. + +## Topics + +### Type Metadata + +- ``Metadata`` + +### Metadata Creation + +- ``Metadata/init(_:)`` + +### Type Properties + +- ``Metadata/description`` + +### Runtime Utilities + +- ``MemoryLayout/offset(of:)`` +- ``PointerOffset`` + +### Memory Layout + +- ``PointerOffset/offset(_:)`` +- ``PointerOffset/byteOffset`` +- ``Attribute/unsafeOffset(at:as:)`` +- ``Attribute/applying(offset:)`` + +### Type Validation + +- ``Attribute/validate()`` +- ``AnyAttribute/verify(type:)`` From 814c79a23e243bd90ec2c90e56e8144254f24ad0 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 7 Sep 2025 00:44:22 +0800 Subject: [PATCH 12/12] Add TupleType documentation --- .../Runtime/TupleType.md | 68 +++++++++++++++++++ .../Runtime/Type-Introspection.md | 18 ++++- .../Runtime/UnsafeMutableTuple.md | 60 ++++++++++++++++ .../Runtime/UnsafeTuple.md | 38 +++++++++++ 4 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/TupleType.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/UnsafeMutableTuple.md create mode 100644 Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/UnsafeTuple.md diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/TupleType.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/TupleType.md new file mode 100644 index 00000000..4f87c363 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/TupleType.md @@ -0,0 +1,68 @@ +# ``TupleType`` + +Runtime support for Swift tuple types with dynamic element access and memory management. + +## Overview + +`TupleType` provides runtime introspection and manipulation capabilities for Swift tuple types. It enables dynamic access to tuple elements, memory layout information, and safe element copying operations without requiring compile-time knowledge of the tuple's structure. + + let tupleType = TupleType([Int.self, String.self, Bool.self]) + let tuple = (42, "Hello", true) + + // Access elements dynamically + let intValue: Int = tuple[0] + let stringValue: String = tuple[1] + let boolValue: Bool = tuple[2] + +TupleType is essential for OpenAttributeGraph's ability to work with heterogeneous data structures while maintaining type safety and efficient memory operations. + +## Key Features + +- Dynamic tuple creation: Create tuple types from arrays of Swift types +- Element access: Safely access tuple elements by index with type checking +- Memory management: Initialize, copy, and destroy tuple elements safely +- Layout introspection: Query element offsets, sizes, and memory layout +- Buffer operations: Work with raw memory buffers containing tuple data + +## Usage with Attributes + +TupleType enables OpenAttributeGraph to create attributes that contain heterogeneous data structures, supporting complex reactive computations over tuple-based data. + +## Topics + +### Creating Tuple Types + +- ``init(_:)`` +- ``init(_:)-9jmk1`` +- ``init(count:elements:)`` + +### Type Properties + +- ``type`` +- ``count`` +- ``size`` +- ``isEmpty`` +- ``indices`` + +### Element Access + +- ``type(at:)`` +- ``elementType(at:)`` +- ``elementSize(at:)`` +- ``elementOffset(at:type:)`` +- ``offset(at:as:)`` + +### Element Operations + +- ``setElement(in:at:from:options:)`` +- ``getElement(in:at:to:options:)`` +- ``destroy(_:)`` +- ``destroy(_:at:)`` + +### Copy Options + +- ``CopyOptions`` + +### Buffer Functions + +- ``withUnsafeTuple(of:count:_:)`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/Type-Introspection.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/Type-Introspection.md index 28491a19..78f4885a 100644 --- a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/Type-Introspection.md +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/Type-Introspection.md @@ -4,21 +4,36 @@ Runtime type information and introspection utilities. ## Overview -Type introspection provides runtime access to Swift type metadata, enabling OpenAttributeGraph to work with types dynamically. +Type introspection provides runtime access to Swift type metadata, enabling OpenAttributeGraph to work with types dynamically. The Metadata system allows the framework to handle type information at runtime, supporting features like type-erased attributes and dynamic type checking. + +TupleType provides specialized support for working with tuple types at runtime, enabling dynamic element access and memory management for heterogeneous data structures. ## Topics ### Type Metadata - ``Metadata`` +- ``TupleType`` ### Metadata Creation - ``Metadata/init(_:)`` +- ``TupleType/init(_:)`` +- ``TupleType/init(_:)-9jmk1`` +- ``TupleType/init(count:elements:)`` ### Type Properties - ``Metadata/description`` +- ``TupleType/type`` +- ``TupleType/count`` +- ``TupleType/size`` + +### Tuple Operations + +- ``UnsafeTuple`` +- ``UnsafeMutableTuple`` +- ``withUnsafeTuple(of:count:_:)`` ### Runtime Utilities @@ -31,6 +46,7 @@ Type introspection provides runtime access to Swift type metadata, enabling Open - ``PointerOffset/byteOffset`` - ``Attribute/unsafeOffset(at:as:)`` - ``Attribute/applying(offset:)`` +- ``TupleType/elementOffset(at:type:)`` ### Type Validation diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/UnsafeMutableTuple.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/UnsafeMutableTuple.md new file mode 100644 index 00000000..54de5069 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/UnsafeMutableTuple.md @@ -0,0 +1,60 @@ +# ``UnsafeMutableTuple`` + +Mutable tuple buffer for dynamic tuple creation, modification, and memory management. + +## Overview + +`UnsafeMutableTuple` extends `UnsafeTuple` with mutation capabilities, allowing creation, modification, and destruction of tuple data. It provides complete lifecycle management for dynamically created tuples with proper memory allocation and cleanup. + + let mutableTuple = UnsafeMutableTuple(with: tupleType) + + // Initialize elements + mutableTuple.initialize(at: 0, to: 42) + mutableTuple.initialize(at: 1, to: "Hello") + + // Access and modify + mutableTuple[0] = 100 + let value: String = mutableTuple[1] + + // Clean up + mutableTuple.deallocate(initialized: true) + +## Key Features + +- Dynamic allocation: Create tuple buffers with proper memory alignment +- Element initialization: Initialize tuple elements in-place with type safety +- Mutation operations: Modify tuple elements after creation +- Memory management: Proper cleanup with element-wise deinitialization +- Lifecycle control: Manual control over initialization and deallocation phases + +## Topics + +### Creating Mutable Tuples + +- ``init(with:)`` + +### Element Initialization + +- ``initialize(at:to:)`` + +### Memory Management + +- ``deinitialize()`` +- ``deinitialize(at:)`` +- ``deallocate(initialized:)`` + +### Tuple Properties + +- ``count`` +- ``isEmpty`` +- ``indices`` + +### Element Access + +- ``subscript()`` +- ``subscript(_:)`` + +### Address Operations + +- ``address(as:)`` +- ``address(of:as:)`` \ No newline at end of file diff --git a/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/UnsafeTuple.md b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/UnsafeTuple.md new file mode 100644 index 00000000..f25c6649 --- /dev/null +++ b/Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/UnsafeTuple.md @@ -0,0 +1,38 @@ +# ``UnsafeTuple`` + +Immutable tuple buffer for safe element access and type-checked operations. + +## Overview + +`UnsafeTuple` provides safe, type-checked access to elements within a tuple stored in a raw memory buffer. It combines tuple type metadata with a pointer to tuple data, enabling runtime inspection and element retrieval while maintaining memory safety. + + withUnsafeTuple(of: tupleType, count: 1) { unsafeTuple in + let firstElement: Int = unsafeTuple[0] + let secondElement: String = unsafeTuple[1] + // Access elements safely with compile-time type checking + } + +## Key Features + +- Type-safe element access: Access tuple elements with automatic type verification +- Index-based operations: Use integer indices to access elements by position +- Memory safety: Bounds checking and type validation prevent unsafe memory access +- Address computation: Get typed pointers to specific tuple elements + +## Topics + +### Tuple Properties + +- ``count`` +- ``isEmpty`` +- ``indices`` + +### Element Access + +- ``subscript()`` +- ``subscript(_:)`` + +### Address Operations + +- ``address(as:)`` +- ``address(of:as:)`` \ No newline at end of file