Skip to content

Add GraphValue and GraphMutation implementation #43

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"location" : "https://github.com/OpenSwiftUIProject/OpenGraph",
"state" : {
"branch" : "main",
"revision" : "45bd9b86eb917e1bd56ead3ef51ca82beca94a70"
"revision" : "10eb096bfdefd73bb50df410b87602208bcc06c1"
}
},
{
Expand Down
111 changes: 88 additions & 23 deletions Sources/OpenSwiftUI/Core/Graph/GraphHost.swift
Original file line number Diff line number Diff line change
@@ -1,33 +1,50 @@
// TODO & WIP
//
// GraphHost.swift
// OpenSwiftUI
//
// Lastest Version: iOS 15.5
// Status: WIP
// ID: 30C09FF16BC95EC5173809B57186CAC3

internal import COpenSwiftUI
internal import OpenGraphShims

class GraphHost {
var data: Data
var isInstantiated: Bool
// var hostPreferenceValues: OptionalAttribute<PreferenceList>
// var lastHostPreferencesSeed: VersionSeed
// var pendingTransactions: [AsyncTransaction]
// var inTransaction: Bool
// var continuations: [() -> ()]
// var mayDeferUpdate: Bool
// var removedState: RemovedState
var hostPreferenceValues: OptionalAttribute<PreferenceList>
var lastHostPreferencesSeed: VersionSeed
private var pendingTransactions: [AsyncTransaction]
var inTransaction: Bool
var continuations: [() -> ()]
var mayDeferUpdate: Bool
var removedState: RemovedState

// FIXME
static var isUpdating = false

// private static let shared = OGGraphCreate()
private static let sharedGraph = OGGraph()

// MARK: - non final methods

init(data: Data) {
self.data = data
isInstantiated = false
// TODO
fatalError("TODO")
}

func invalidate() {
// TODO
if isInstantiated {
// data.globalSubgraph.apply
isInstantiated = false
}
if let _ = data.graph {
data.globalSubgraph.invalidate()
// graph.context = nil
// graph.invalidate()
data.graph = nil
}
}

var graphDelegate: GraphDelegate? { nil }
Expand Down Expand Up @@ -56,22 +73,42 @@ extension GraphHost {
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 isRemoved = false
var isHiddenForReuse = false
@Attribute var time: Time
@Attribute var environment: EnvironmentValues
@Attribute var phase: _GraphInputs.Phase
@Attribute var hostPreferenceKeys: PreferenceKeys
@Attribute var transaction: Transaction
var inputs: _GraphInputs

init() {
fatalError("TODO")
let graph = OGGraph(shared: GraphHost.sharedGraph)
let globalSubgraph = OGSubgraph(graph: graph)
OGSubgraph.current = globalSubgraph
let time = Attribute(value: Time.zero)
let environment = Attribute(value: EnvironmentValues())
let phase = Attribute(value: _GraphInputs.Phase(value: 0))
let hostPreferenceKeys = Attribute(value: PreferenceKeys())
let transaction = Attribute(value: Transaction())
let cachedEnvironment = MutableBox(CachedEnvironment(environment))
let rootSubgrph = OGSubgraph(graph: graph)
globalSubgraph.addChild(rootSubgrph)
OGSubgraph.current = nil
self.graph = graph
self.globalSubgraph = globalSubgraph
self.rootSubgraph = rootSubgrph
_time = time
_environment = environment
_phase = phase
_hostPreferenceKeys = hostPreferenceKeys
_transaction = transaction
inputs = _GraphInputs(
time: time,
cachedEnvironment: cachedEnvironment,
phase: phase,
transaction: transaction
)
}
}
}
Expand All @@ -84,3 +121,31 @@ extension GraphHost {
let rawValue: UInt8
}
}

// MARK: - AsyncTransaction

private final class AsyncTransaction {
let transaction: Transaction
var mutations: [GraphMutation] = []

init(_ transaction: Transaction) {
self.transaction = transaction
}

func append<Mutation: GraphMutation>(_ mutation: Mutation) {
// ``GraphMutation/combine`` is mutating function
// So we use ``Array.subscript/_modify`` instead of ``Array.last/getter`` to mutate inline
if !mutations.isEmpty, mutations[mutations.count-1].combine(with: mutation) {
return
}
mutations.append(mutation)
}

func apply() {
withTransaction(transaction) {
for mutation in mutations {
mutation.apply()
}
}
}
}
28 changes: 24 additions & 4 deletions Sources/OpenSwiftUI/Core/Graph/GraphInputs.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
internal import OpenGraphShims

// FIXME: Compile crash on non-Darwin platform
// https://github.com/OpenSwiftUIProject/OpenSwiftUI/issues/39
#if !canImport(Darwin)
typealias OGAttribute = UInt32
#endif

public struct _GraphInputs {
var customInputs: PropertyList
var time: Attribute<Time>
Expand All @@ -8,11 +14,25 @@ public struct _GraphInputs {
var transaction: Attribute<Transaction>
var changedDebugProperties: _ViewDebug.Properties
var options: _GraphInputs.Options
// FIXME: Compile crash on non-Darwin platform
// https://github.com/OpenSwiftUIProject/OpenSwiftUI/issues/39
#if canImport(Darwin)
var mergedInputs: Set<OGAttribute>
#endif

init(customInputs: PropertyList = PropertyList(),
time: Attribute<Time>,
cachedEnvironment: MutableBox<CachedEnvironment>,
phase: Attribute<Phase>,
transaction: Attribute<Transaction>,
changedDebugProperties: _ViewDebug.Properties = [],
options: _GraphInputs.Options = [],
mergedInputs: Set<OGAttribute> = []) {
self.customInputs = customInputs
self.time = time
self.cachedEnvironment = cachedEnvironment
self.phase = phase
self.transaction = transaction
self.changedDebugProperties = changedDebugProperties
self.options = options
self.mergedInputs = mergedInputs
}

subscript<Input: GraphInput>(_ type: Input.Type) -> Input.Value {
get { customInputs[type] }
Expand Down
50 changes: 50 additions & 0 deletions Sources/OpenSwiftUI/Core/Graph/GraphMutation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// GraphMutation.swift
// OpenSwiftUI
//
// Audited for RELEASE_2021
// Status: Complete

internal import OpenGraphShims

protocol GraphMutation {
func apply()
mutating func combine<Mutation: GraphMutation>(with: Mutation) -> Bool
}

struct EmptyGraphMutation: GraphMutation {
func apply() {}
func combine<Mutation>(with _: Mutation) -> Bool where Mutation: GraphMutation {
Mutation.self == EmptyGraphMutation.self
}
}

// FIXME: #39
#if canImport(Darwin)
struct InvalidatingGraphMutation: GraphMutation {
let attribute: OGWeakAttribute

func apply() {
attribute.attribute?.invalidateValue()
}

func combine(with mutation: some GraphMutation) -> Bool {
guard let mutation = mutation as? InvalidatingGraphMutation else {
return false
}
return mutation.attribute == attribute
}
}
#endif

struct CustomGraphMutation: GraphMutation {
let body: () -> Void

func apply() {
body()
}

func combine(with _: some GraphMutation) -> Bool {
false
}
}
34 changes: 15 additions & 19 deletions Sources/OpenSwiftUI/Core/Graph/GraphValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,39 @@
// OpenSwiftUI
//
// Audited for RELEASE_2021
// Status: WIP
// Status: Complete

internal import OpenGraphShims

public struct _GraphValue<Value>: Equatable {
public subscript<U>(keyPath keyPath: KeyPath<Value, U>) -> _GraphValue<U> {
_GraphValue<U>(value[keyPath: keyPath])
}

public static func == (a: _GraphValue<Value>, b: _GraphValue<Value>) -> Bool {
a.value == b.value
}

var value: Attribute<Value>

init(_ value: Attribute<Value>) {
self.value = value
}

init<R: Rule>(_ rule: R) where R.Value == Value {
fatalError("TODO")
value = Attribute(rule)
}

init<R: StatefulRule>(_ rule: R) where R.Value == Value {
fatalError("TODO")
value = Attribute(rule)
}

subscript<Member>(offset body: (inout Value) -> PointerOffset<Value, Member>) -> _GraphValue<Member> {
.init(value[offset: body])
func unsafeBitCast<V>(to type: V.Type) -> _GraphValue<V> {
_GraphValue<V>(value.unsafeBitCast(to: type))
}

subscript<Member>(keyPath: KeyPath<Value, Member>) -> _GraphValue<Member> {
.init(value[keyPath: keyPath])
public subscript<Member>(keyPath: KeyPath<Value, Member>) -> _GraphValue<Member> {
_GraphValue<Member>(value[keyPath: keyPath])
}

func unsafeBitCast<V>(to type: V.Type) -> _GraphValue<V> {
.init(value.unsafeBitCast(to: type))
subscript<Member>(offset body: (inout Value) -> PointerOffset<Value, Member>) -> _GraphValue<Member> {
_GraphValue<Member>(value[offset: body])
}

public static func == (a: _GraphValue<Value>, b: _GraphValue<Value>) -> Bool {
a.value == b.value
}
}

Expand Down
3 changes: 2 additions & 1 deletion Sources/OpenSwiftUI/Core/Util/Time.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ struct Time: Comparable, Hashable {
lhs.seconds < rhs.seconds
}

static var infinity: Time { Time(seconds: .infinity) }
static let zero = Time(seconds: .zero)
static let infinity = Time(seconds: .infinity)
}
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
struct CachedEnvironment {}
internal import OpenGraphShims

struct CachedEnvironment {
init(_ environment: Attribute<EnvironmentValues>) {
fatalError("TODO")
}
}