diff --git a/Package.resolved b/Package.resolved index b0380e4..4ba7be1 100644 --- a/Package.resolved +++ b/Package.resolved @@ -6,7 +6,7 @@ "location" : "https://github.com/OpenSwiftUIProject/OpenGraph", "state" : { "branch" : "main", - "revision" : "8cc89abc1fff74b387a083eab8ffa91f1b9fdca7" + "revision" : "6133e9f737077b5c75ff33dee1c2c969cb5d91b4" } }, { @@ -14,8 +14,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-syntax.git", "state" : { - "revision" : "6ad4ea24b01559dde0773e3d091f1b9e36175036", - "version" : "509.0.2" + "revision" : "64889f0c732f210a935a0ad7cda38f77f876262d", + "version" : "509.1.1" } }, { diff --git a/Scripts/demangle.sh b/Scripts/demangle.sh new file mode 100755 index 0000000..0e34b42 --- /dev/null +++ b/Scripts/demangle.sh @@ -0,0 +1,30 @@ +#!/bin/zsh + +# A `realpath` alternative using the default C implementation. +filepath() { + [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" +} + +OG_ROOT="$(dirname $(dirname $(filepath $0)))" + +# Get the language and input file path from the arguments +language=${1:-"swift"} +input_file=${2:-"$(dirname $(filepath $0))/demangle.txt"} + +echo "Demangling $input_file using $language mode" + +# Read each line of the input file +while IFS= read -r line; do + # Demangle the line using the appropriate tool based on the language + if [[ $language == "swift" ]]; then + xcrun swift-demangle "$line" + elif [[ $language == "c++" ]]; then + c++filt "$line" + else + echo "Invalid language: $language" + echo "Usage: demangle.sh " + echo "language: swift or c++, [default]: swift" + echo "input file: [default] demangle.txt" + exit 1 + fi +done < "$input_file" diff --git a/Scripts/demangle.txt b/Scripts/demangle.txt new file mode 100644 index 0000000..e69de29 diff --git a/Scripts/openswiftui_swiftinterface.sh b/Scripts/openswiftui_swiftinterface.sh new file mode 100755 index 0000000..9632409 --- /dev/null +++ b/Scripts/openswiftui_swiftinterface.sh @@ -0,0 +1,14 @@ +#!/bin/zsh + +# A `realpath` alternative using the default C implementation. +filepath() { + [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" +} + +OPENSWIFTUI_ROOT="$(dirname $(dirname $(filepath $0)))" + +cd $OPENSWIFTUI_ROOT + +export OPENSWIFTUI_SWIFT_TESTING=0 +export OPENGRAPH_SWIFT_TESTING=0 +swift build -c release -Xswiftc -emit-module-interface -Xswiftc -enable-library-evolution diff --git a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicProperty.swift b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicProperty.swift index 8ded783..92044b9 100644 --- a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicProperty.swift +++ b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicProperty.swift @@ -5,6 +5,9 @@ // Created by Kyle on 2023/11/2. // Lastest Version: iOS 15.5 // Status: Complete +// ID: 49D2A32E637CD497C6DE29B8E060A506 + +internal import OpenGraphShims /// An interface for a stored variable that updates an external property of a /// view. @@ -29,8 +32,209 @@ public protocol DynamicProperty { mutating func update() } +// MARK: Default implementation for DynamicProperty + extension DynamicProperty { + public static func _makeProperty( + in buffer: inout _DynamicPropertyBuffer, + container: _GraphValue, + fieldOffset: Int, + inputs: inout _GraphInputs + ) { + makeEmbeddedProperties( + in: &buffer, + container: container, + fieldOffset: fieldOffset, + inputs: &inputs + ) + buffer.append( + EmbeddedDynamicPropertyBox(), + fieldOffset: fieldOffset + ) + } + public static var _propertyBehaviors: UInt32 { 0 } public mutating func update() {} } + +// MARK: - EmbeddedDynamicPropertyBox + +private struct EmbeddedDynamicPropertyBox: DynamicPropertyBox { + typealias Property = Value + func destroy() {} + func reset() {} + func update(property: inout Property, phase _: _GraphInputs.Phase) -> Bool { + property.update() + return false + } +} + +extension DynamicProperty { + static func makeEmbeddedProperties( + in buffer: inout _DynamicPropertyBuffer, + container: _GraphValue, + fieldOffset: Int, + inputs: inout _GraphInputs + ) { + let fields = DynamicPropertyCache.fields(of: self) + buffer.addFields( + fields, + container: container, + inputs: &inputs, + baseOffset: fieldOffset + ) + } +} + +// FIXME: Compile crash on non-ObjectiveC platform +// https://github.com/OpenSwiftUIProject/OpenSwiftUI/issues/39 +#if canImport(Darwin) +extension BodyAccessor { + func makeBody( + container: _GraphValue, + inputs: inout _GraphInputs, + fields: DynamicPropertyCache.Fields + ) -> (_GraphValue, _DynamicPropertyBuffer?) { + guard Body.self != Never.self else { + fatalError("\(Body.self) may not have Body == Never") + } + return withUnsafeMutablePointer(to: &inputs) { inputsPointer in + func project(flags _: Flags.Type) -> (_GraphValue, _DynamicPropertyBuffer?) { + let buffer = _DynamicPropertyBuffer( + fields: fields, + container: container, + inputs: &inputsPointer.pointee + ) + if buffer._count == 0 { + buffer.destroy() + let body = StaticBody( + accessor: self, + container: container.value + ) + return (_GraphValue(body), nil) + } else { + let body = DynamicBody( + accessor: self, + container: container.value, + phase: inputsPointer.pointee.phase, + links: buffer, + resetSeed: 0 + ) + return (_GraphValue(body), buffer) + } + } + if fields.behaviors.contains(.asyncThread) { + return project(flags: AsyncThreadFlags.self) + } else { + return project(flags: MainThreadFlags.self) + } + } + } +} + +// MARK: - RuleThreadFlags + +private protocol RuleThreadFlags { + static var value: OGAttributeTypeFlags { get } +} + +private struct AsyncThreadFlags: RuleThreadFlags { + static var value: OGAttributeTypeFlags { .asyncThread } +} + +private struct MainThreadFlags: RuleThreadFlags { + static var value: OGAttributeTypeFlags { .mainThread } +} + +// MARK: - StaticBody + +private struct StaticBody { + let accessor: Accessor + @Attribute + var container: Accessor.Container + + init(accessor: Accessor, container: Attribute) { + self.accessor = accessor + self._container = container + } +} + +extension StaticBody: StatefulRule { + typealias Value = Accessor.Body + + func updateValue() { + accessor.updateBody(of: container, changed: true) + } +} + +extension StaticBody: _AttributeBody { + static var flags: OGAttributeTypeFlags { + ThreadFlags.value + } +} + +extension StaticBody: BodyAccessorRule { + static var container: Any.Type { + Accessor.Container.self + } + + static func buffer(as type: Value.Type, attribute: OGAttribute) -> _DynamicPropertyBuffer? { + nil + } + + static func value(as type: Value.Type, attribute: OGAttribute) -> Value? { + guard container == type else { + return nil + } + return (attribute.info.body.assumingMemoryBound(to: Self.self).pointee.container as! Value) + } + + static func metaProperties(as type: Value.Type, attribute: OGAttribute) -> [(String, OGAttribute)] { + guard container == type else { + return [] + } + return [("@self", attribute.info.body.assumingMemoryBound(to: Self.self).pointee._container.identifier)] + } +} + +extension StaticBody: CustomStringConvertible { + var description: String { "\(Accessor.Body.self)" } +} + +// MARK: - DynamicBody + +// TODO +private struct DynamicBody { + let accessor: Accessor + @Attribute + var container: Accessor.Container + @Attribute + var phase: _GraphInputs.Phase + var links: _DynamicPropertyBuffer + var resetSeed: UInt32 + + init( + accessor: Accessor, + container: Attribute, + phase: Attribute<_GraphInputs.Phase>, + links: _DynamicPropertyBuffer, + resetSeed: UInt32 + ) { + fatalError("TODO") +// self.accessor = accessor +// self._container = container +// self._phase = phase +// self.links = links +// self.resetSeed = resetSeed + } +} + +extension DynamicBody: StatefulRule { + typealias Value = Accessor.Body + + func updateValue() { + // TODO + } +} +#endif diff --git a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyBehaviors.swift b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyBehaviors.swift index eb755ba..48a12bd 100644 --- a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyBehaviors.swift +++ b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyBehaviors.swift @@ -8,4 +8,5 @@ struct DynamicPropertyBehaviors: OptionSet { let rawValue: UInt32 + static var asyncThread: DynamicPropertyBehaviors { .init(rawValue: 1 << 0) } } diff --git a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyBuffer.swift b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyBuffer.swift index 7c194f7..a5821c5 100644 --- a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyBuffer.swift +++ b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyBuffer.swift @@ -26,7 +26,7 @@ public struct _DynamicPropertyBuffer { fields: DynamicPropertyCache.Fields, container: _GraphValue, inputs: inout _GraphInputs, - baseOffset: Int + baseOffset: Int = 0 ) { self.init() addFields(fields, container: container, inputs: &inputs, baseOffset: baseOffset) diff --git a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyCache.swift b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyCache.swift index 68fa002..2ea177f 100644 --- a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyCache.swift +++ b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyCache.swift @@ -113,50 +113,3 @@ extension DynamicPropertyCache { var fields: [Field] } } - -// MARK: - EmbeddedDynamicPropertyBox - -private struct EmbeddedDynamicPropertyBox: DynamicPropertyBox { - typealias Property = Value - func destroy() {} - func reset() {} - func update(property: inout Property, phase _: _GraphInputs.Phase) -> Bool { - property.update() - return false - } -} - -extension DynamicProperty { - public static func _makeProperty( - in buffer: inout _DynamicPropertyBuffer, - container: _GraphValue, - fieldOffset: Int, - inputs: inout _GraphInputs - ) { - makeEmbeddedProperties( - in: &buffer, - container: container, - fieldOffset: fieldOffset, - inputs: &inputs - ) - buffer.append( - EmbeddedDynamicPropertyBox(), - fieldOffset: fieldOffset - ) - } - - static func makeEmbeddedProperties( - in buffer: inout _DynamicPropertyBuffer, - container: _GraphValue, - fieldOffset: Int, - inputs: inout _GraphInputs - ) -> () { - let fields = DynamicPropertyCache.fields(of: self) - buffer.addFields( - fields, - container: container, - inputs: &inputs, - baseOffset: fieldOffset - ) - } -} diff --git a/Sources/OpenSwiftUI/Internal/BodyAccessor/BodyAccessor.swift b/Sources/OpenSwiftUI/Internal/BodyAccessor/BodyAccessor.swift new file mode 100644 index 0000000..07594af --- /dev/null +++ b/Sources/OpenSwiftUI/Internal/BodyAccessor/BodyAccessor.swift @@ -0,0 +1,13 @@ +// +// BodyAccessor.swift +// OpenSwiftUI +// +// Created by Kyle on 2024/2/21. +// Lastest Version: iOS 15.5 +// Status: Complete + +protocol BodyAccessor { + associatedtype Container + associatedtype Body + func updateBody(of: Container, changed: Bool) +} diff --git a/Sources/OpenSwiftUI/Internal/BodyAccessor/BodyAccessorRule.swift b/Sources/OpenSwiftUI/Internal/BodyAccessor/BodyAccessorRule.swift new file mode 100644 index 0000000..43f34e9 --- /dev/null +++ b/Sources/OpenSwiftUI/Internal/BodyAccessor/BodyAccessorRule.swift @@ -0,0 +1,16 @@ +// +// BodyAccessorRule.swift +// OpenSwiftUI +// +// Created by Kyle on 2024/2/21. +// Lastest Version: iOS 15.5 +// Status: Complete + +internal import OpenGraphShims + +protocol BodyAccessorRule { + static var container: Any.Type { get } + static func value(as: Value.Type, attribute: OGAttribute) -> Value? + static func buffer(as: Value.Type, attribute: OGAttribute) -> _DynamicPropertyBuffer? + static func metaProperties(as: Value.Type, attribute: OGAttribute) -> [(String, OGAttribute)] +} diff --git a/Sources/OpenSwiftUI/Internal/Graph/_Graph.swift b/Sources/OpenSwiftUI/Internal/Graph/Graph.swift similarity index 72% rename from Sources/OpenSwiftUI/Internal/Graph/_Graph.swift rename to Sources/OpenSwiftUI/Internal/Graph/Graph.swift index 7e6985f..f42b8e6 100644 --- a/Sources/OpenSwiftUI/Internal/Graph/_Graph.swift +++ b/Sources/OpenSwiftUI/Internal/Graph/Graph.swift @@ -1,10 +1,9 @@ // -// _Graph.swift +// Graph.swift // OpenSwiftUI // // Created by Kyle on 2023/9/24. // Lastest Version: iOS 15.5 // Status: Complete -public struct _Graph { -} +public struct _Graph {} diff --git a/Sources/OpenSwiftUI/Internal/Graph/GraphHost.swift b/Sources/OpenSwiftUI/Internal/Graph/GraphHost.swift new file mode 100644 index 0000000..fab39cf --- /dev/null +++ b/Sources/OpenSwiftUI/Internal/Graph/GraphHost.swift @@ -0,0 +1,53 @@ +// TODO & WIP + +internal import OpenGraphShims + +class GraphHost { + +// var data: Data +// var isInstantiated: Swift.Bool +// var hostPreferenceValues: OptionalAttribute +// var lastHostPreferencesSeed: VersionSeed +// var pendingTransactions: [SwiftUI.(AsyncTransaction in _30C09FF16BC95EC5173809B57186CAC3)] +// var inTransaction: Bool +// var continuations: [() -> ()] +// var mayDeferUpdate: Bool +// var removedState: RemovedState + + static var isUpdating = false + + +// private static let shared = OGGraphCreate() +} + +// MARK: - GraphHost.Data + +extension GraphHost { + struct Data { + var graph: OGGraph? + var globalSubgraph: OGSubgraph + var rootSubgraph: OGSubgraph + var isRemoved: Bool + var isHiddenForReuse: Bool + @Attribute + var time: Time + @Attribute + var environment: EnvironmentValues + @Attribute + var phase: _GraphInputs.Phase + @Attribute + var hostPreferenceKeys: PreferenceKeys + @Attribute + var transaction: Transaction + var inputs: _GraphInputs + } +} + +// MARK: - GraphHost.RemovedState + +extension GraphHost { + // TODO + struct RemovedState: OptionSet { + let rawValue: UInt8 + } +} diff --git a/Sources/OpenSwiftUI/Internal/Graph/TODO/_GraphInputs.swift b/Sources/OpenSwiftUI/Internal/Graph/GraphInputs.swift similarity index 65% rename from Sources/OpenSwiftUI/Internal/Graph/TODO/_GraphInputs.swift rename to Sources/OpenSwiftUI/Internal/Graph/GraphInputs.swift index 068891b..c2a1019 100644 --- a/Sources/OpenSwiftUI/Internal/Graph/TODO/_GraphInputs.swift +++ b/Sources/OpenSwiftUI/Internal/Graph/GraphInputs.swift @@ -8,14 +8,20 @@ public struct _GraphInputs { var transaction: Attribute var changedDebugProperties: _ViewDebug.Properties var options: _GraphInputs.Options - // FIXME: Compile crash on Linux + // FIXME: Compile crash on non-Darwin platform + // https://github.com/OpenSwiftUIProject/OpenSwiftUI/issues/39 #if canImport(Darwin) var mergedInputs: Set #endif + + subscript(_ type: Input.Type) -> Input.Value { + get { customInputs[type] } + set { customInputs[type] = newValue } + } } extension _GraphInputs { - struct Phase { + struct Phase: Equatable { let value: UInt32 } } diff --git a/Sources/OpenSwiftUI/Internal/Graph/_GraphInputsModifier.swift b/Sources/OpenSwiftUI/Internal/Graph/GraphInputsModifier.swift similarity index 100% rename from Sources/OpenSwiftUI/Internal/Graph/_GraphInputsModifier.swift rename to Sources/OpenSwiftUI/Internal/Graph/GraphInputsModifier.swift diff --git a/Sources/OpenSwiftUI/Internal/Graph/GraphValue.swift b/Sources/OpenSwiftUI/Internal/Graph/GraphValue.swift new file mode 100644 index 0000000..328418e --- /dev/null +++ b/Sources/OpenSwiftUI/Internal/Graph/GraphValue.swift @@ -0,0 +1,51 @@ +// +// GraphValue.swift +// OpenSwiftUI +// +// Created by Kyle on 2024/2/21. +// Lastest Version: iOS 15.5 +// Status: WIP + +internal import OpenGraphShims + +public struct _GraphValue: Equatable { + public subscript(keyPath keyPath: KeyPath) -> _GraphValue { + _GraphValue(value[keyPath: keyPath]) + } + + public static func == (a: _GraphValue, b: _GraphValue) -> Bool { + a.value == b.value + } + + var value: Attribute + + init(_ value: Attribute) { + self.value = value + } + + init(_ rule: R) where R.Value == Value { + fatalError("TODO") + } + + init(_ rule: R) where R.Value == Value { + fatalError("TODO") + } + + subscript(offset body: (inout Value) -> PointerOffset) -> _GraphValue { + .init(value[offset: body]) + } + + subscript(keyPath: KeyPath) -> _GraphValue { + .init(value[keyPath: keyPath]) + } + + func unsafeBitCast(to type: V.Type) -> _GraphValue { + .init(value.unsafeBitCast(to: type)) + } +} + +extension Attribute { + func unsafeBitCast(to type: V.Type) -> Attribute { + unsafeOffset(at: 0, as: V.self) + } +} diff --git a/Sources/OpenSwiftUI/Internal/Graph/TODO/GraphHost.swift b/Sources/OpenSwiftUI/Internal/Graph/TODO/GraphHost.swift deleted file mode 100644 index 875251b..0000000 --- a/Sources/OpenSwiftUI/Internal/Graph/TODO/GraphHost.swift +++ /dev/null @@ -1,4 +0,0 @@ -// TODO & WIP -class GraphHost { - static var isUpdating = false -} diff --git a/Sources/OpenSwiftUI/Internal/Graph/TODO/_GraphValue.swift b/Sources/OpenSwiftUI/Internal/Graph/TODO/_GraphValue.swift deleted file mode 100644 index 59ef83d..0000000 --- a/Sources/OpenSwiftUI/Internal/Graph/TODO/_GraphValue.swift +++ /dev/null @@ -1,18 +0,0 @@ -internal import OpenGraphShims - -public struct _GraphValue: Equatable { - var value: Attribute - - public subscript(keyPath: KeyPath) -> _GraphValue { -// _GraphValue(value[keyPath]) - fatalError() - } - - public static func == (a: _GraphValue, b: _GraphValue) -> Bool { - a.value == b.value - } - - init(_ attribute: Attribute) { - self.value = attribute - } -}