├── Scripts ├── demangle.txt ├── CI │ ├── darwin_setup_build.sh │ ├── ag_setup.sh │ └── get_revision.sh ├── build.sh ├── build_swiftinterface.sh ├── demangle.sh └── gen_ag_template.sh ├── Tests ├── OpenAttributeGraphShimsTests │ ├── OpenAttributeGraphTestsSupport │ ├── Export.swift │ ├── README.md │ ├── Attribute+DebugTests.swift │ └── MetadataDebugTests.swift ├── OpenAttributeGraphCompatibilityTests │ ├── OpenAttributeGraphTestsSupport │ ├── README.md │ ├── Data │ │ └── UniqueIDCompatibilityTests.swift │ ├── Graph │ │ ├── GraphDescriptionCompatibilityTests.swift │ │ └── GraphTracingCompatibilityTests.swift │ ├── Attribute │ │ ├── Rule │ │ │ ├── RuleCompatibilityTests.swift │ │ │ └── MapCompatibilityTests.swift │ │ ├── Weak │ │ │ ├── WeakAttributeCompatibilityTests.swift │ │ │ └── AnyWeakAttributeCompatibilityTests.swift │ │ ├── Indirect │ │ │ └── IndirectAttributeCompatibilityTests.swift │ │ ├── Attribute │ │ │ ├── FocusCompatibilityTests.swift │ │ │ ├── ExternalCompatibilityTests.swift │ │ │ └── AttributeCompatibilityTests.swift │ │ └── Optional │ │ │ ├── OptionalAttributeCompatibilityTests.swift │ │ │ └── AnyOptionalAttributeCompatibilityTests.swift │ ├── GraphShims.swift │ ├── VersionCompatibilityTests.swift │ └── Debug │ │ └── DebugServerTests.swift ├── OpenAttributeGraphCxxTests │ ├── DebugServer │ │ ├── DebugClient.swift │ │ ├── DebugServerMessageHeader.swift │ │ └── DebugServerTests.swift │ ├── README.md │ ├── Data │ │ ├── PageTests.swift │ │ ├── ZoneTests.swift │ │ └── TableTests.swift │ └── Util │ │ ├── ForwardListTests.swift │ │ └── HeapTests.swift ├── OpenAttributeGraphTests │ ├── README.md │ └── DummyTests.swift └── OpenAttributeGraphTestsSupport │ ├── DataHelper.swift │ └── GraphEnvironmentTrait.swift ├── .spi.yml ├── Sources ├── OpenAttributeGraph │ ├── Debug │ │ └── DebugServer.swift │ ├── Export.swift │ ├── Attribute │ │ ├── Body │ │ │ ├── AttributeBodyVisitor.swift │ │ │ ├── ObservedAttribute.swift │ │ │ └── AttributeBody.swift │ │ ├── Rule │ │ │ ├── Map.swift │ │ │ ├── Focus.swift │ │ │ └── StatefulRule.swift │ │ ├── Attribute │ │ │ ├── External.swift │ │ │ ├── PointerOffset.swift │ │ │ └── AnyAttribute.swift │ │ ├── Weak │ │ │ └── AnyWeakAttribute.swift │ │ ├── Optional │ │ │ ├── AnyOptionalAttribute.swift │ │ │ └── OptionalAttribute.swift │ │ ├── Indirect │ │ │ └── IndirectAttribute.swift │ │ └── RuleContext │ │ │ ├── AnyRuleContext.swift │ │ │ └── RuleContext.swift │ ├── OpenAttributeGraph.docc │ │ ├── Attribute │ │ │ ├── Rule │ │ │ │ ├── Focus.md │ │ │ │ ├── StatefulRule.md │ │ │ │ └── Rule.md │ │ │ ├── Weak │ │ │ │ └── WeakAttribute.md │ │ │ ├── Reactive-Attributes.md │ │ │ ├── Attribute │ │ │ │ └── Attribute.md │ │ │ ├── Computed-Attributes.md │ │ │ ├── Attribute-References.md │ │ │ ├── RuleContext │ │ │ │ └── RuleContext.md │ │ │ └── Optional │ │ │ │ └── OptionalAttribute.md │ │ ├── Info.plist │ │ ├── OpenAttributeGraph.md │ │ ├── Runtime │ │ │ ├── UnsafeTuple.md │ │ │ ├── Metadata.md │ │ │ ├── Type-Introspection.md │ │ │ ├── UnsafeMutableTuple.md │ │ │ └── TupleType.md │ │ └── Graph │ │ │ ├── Subgraph.md │ │ │ ├── Dependency-Graphs.md │ │ │ └── Graph.md │ ├── Runtime │ │ ├── OGTypeApplyEnumData.swift │ │ ├── CompareValues.swift │ │ └── Metadata.swift │ └── Graph │ │ └── Subgraph.swift ├── OpenAttributeGraphCxx │ ├── Attribute │ │ ├── AttributeType.cpp │ │ ├── AttributeID.cpp │ │ └── OAGWeakAttribute.cpp │ ├── Data │ │ ├── ClosureFunction.cpp │ │ └── OAGUniqueID.c │ ├── include │ │ ├── module.modulemap │ │ ├── OpenAttributeGraphCxx │ │ │ ├── Misc │ │ │ │ ├── assert.hpp │ │ │ │ ├── env.hpp │ │ │ │ └── log.hpp │ │ │ ├── Attribute │ │ │ │ ├── AttributeType.hpp │ │ │ │ └── AttributeID.hpp │ │ │ ├── Data │ │ │ │ ├── page.hpp │ │ │ │ ├── page_const.hpp │ │ │ │ ├── ClosureFunction.hpp │ │ │ │ ├── zone.hpp │ │ │ │ └── ptr.hpp │ │ │ ├── Vector │ │ │ │ └── realloc_vector.hpp │ │ │ ├── Util │ │ │ │ ├── free_deleter.hpp │ │ │ │ ├── Heap.hpp │ │ │ │ ├── cf_ptr.hpp │ │ │ │ └── objc_ptr.hpp │ │ │ ├── Comparison │ │ │ │ └── OAGComparisonPrivate.h │ │ │ └── Runtime │ │ │ │ └── metadata.hpp │ │ ├── OpenAttributeGraph │ │ │ ├── OAGInputOptions.h │ │ │ ├── OAGChangedValueFlags.h │ │ │ ├── OAGValue.h │ │ │ ├── OAGSearchOptions.h │ │ │ ├── OAGWeakValue.h │ │ │ ├── OAGAttributeInfo.h │ │ │ ├── OAGUniqueID.h │ │ │ ├── OAGAttributeFlags.h │ │ │ ├── OAGValueOptions.h │ │ │ ├── OAGCachedValueOptions.h │ │ │ ├── OAGVersion.h │ │ │ ├── OAGGraphContext.h │ │ │ ├── OAGValueState.h │ │ │ ├── OAGClosure.h │ │ │ ├── OAGAttributeTypeFlags.h │ │ │ ├── OAGGraphCounterQueryType.h │ │ │ ├── OAGWeakAttribute.h │ │ │ ├── OAGSwiftSupport.h │ │ │ ├── OAGAttributeType.h │ │ │ ├── OpenAttributeGraph-umbrella.h │ │ │ ├── OAGGraphTracing.h │ │ │ ├── OAGGraphDescription.h │ │ │ ├── OAGBase.h │ │ │ ├── OAGComparison.h │ │ │ └── OAGTupleType.h │ │ └── module.private.modulemap │ ├── Graph │ │ ├── OAGGraphContext.cpp │ │ ├── OAGGraphTracing.cpp │ │ ├── GraphDescription.mm │ │ ├── GraphContext.cpp │ │ ├── GraphDescription.cpp │ │ ├── Subgraph.cpp │ │ ├── Graph.cpp │ │ └── Graph.mm │ ├── Runtime │ │ └── metadata.cpp │ ├── Misc │ │ ├── log.cpp │ │ └── assert.cpp │ ├── Version │ │ └── OAGVersion.c │ ├── DebugServer │ │ ├── OAGDebugServer.cpp │ │ └── interpose.c │ ├── Comparison │ │ └── OAGComparison.cpp │ ├── Vector │ │ └── realloc_vector.cpp │ └── Util │ │ └── Heap.cpp └── OpenAttributeGraphShims │ ├── DebugServerMessageHeader.swift │ ├── GraphShims.swift │ ├── Graph+Debug.swift │ └── Attribute+Debug.swift ├── Docs ├── Version.md └── Status.md ├── .codecov.yml ├── .gitignore ├── .github └── workflows │ ├── issue-triage.yml │ ├── pr-triage.yml │ ├── claude.yml │ ├── ubuntu.yml │ ├── compatibility_tests.yml │ ├── macos.yml │ └── ios.yml ├── Package.resolved ├── LICENSE ├── CREDITS.md └── CLAUDE.md /Scripts/demangle.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphShimsTests/OpenAttributeGraphTestsSupport: -------------------------------------------------------------------------------- 1 | ../OpenAttributeGraphTestsSupport -------------------------------------------------------------------------------- /.spi.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | builder: 3 | configs: 4 | - documentation_targets: [OpenAttributeGraph] 5 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Debug/DebugServer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DebugServer.swift 3 | // 4 | // 5 | // 6 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/OpenAttributeGraphTestsSupport: -------------------------------------------------------------------------------- 1 | ../OpenAttributeGraphTestsSupport -------------------------------------------------------------------------------- /Docs/Version.md: -------------------------------------------------------------------------------- 1 | # Version 2 | 3 | RELEASE_2021 - iOS 15.5 - macOS 12.7.1 4 | 5 | RELEASE_2023 - iOS 17.0 - macOS 14.0 6 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCxxTests/DebugServer/DebugClient.swift: -------------------------------------------------------------------------------- 1 | ../../../Sources/OpenAttributeGraphShims/DebugClient.swift -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCxxTests/README.md: -------------------------------------------------------------------------------- 1 | ## OpenAttributeGraphCxxTests 2 | 3 | Test internal C++ API of OpenAttributeGraphCxx 4 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCxxTests/DebugServer/DebugServerMessageHeader.swift: -------------------------------------------------------------------------------- 1 | ../../../Sources/OpenAttributeGraphShims/DebugServerMessageHeader.swift -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Export.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Export.swift 3 | // OpenAttributeGraph 4 | 5 | @_exported public import OpenAttributeGraphCxx 6 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphShimsTests/Export.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Export.swift 3 | // OpenAttributeGraphShimsTests 4 | 5 | @_exported import OpenAttributeGraphShims 6 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Attribute/AttributeType.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // OAGAttributeType.cpp 3 | // OpenAttributeGraphCxx 4 | 5 | #include 6 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Attribute/AttributeID.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // AttributeID.cpp 3 | // OpenAttributeGraphCxx 4 | 5 | #include 6 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Data/ClosureFunction.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // ClosureFunction.cpp 3 | // OpenAttributeGraphCxx 4 | 5 | #include 6 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphTests/README.md: -------------------------------------------------------------------------------- 1 | ## OpenAttributeGraphTests 2 | 3 | Test internal API of OpenAttributeGraph 4 | 5 | ```swift 6 | @testable import OpenAttributeGraph 7 | ``` 8 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphTests/DummyTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DummyTests.swift 3 | // OpenAttributeGraphTests 4 | 5 | import OpenAttributeGraph 6 | import Testing 7 | 8 | struct DummyTests {} 9 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphShimsTests/README.md: -------------------------------------------------------------------------------- 1 | ## OpenAttributeGraphShimsTests 2 | 3 | Test OpenAttributeGraphShims Debug API 4 | 5 | ```swift 6 | @_spi(Debug) import OpenAttributeGraphShims 7 | ``` 8 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/module.modulemap: -------------------------------------------------------------------------------- 1 | module OpenAttributeGraphCxx { 2 | export * 3 | } 4 | 5 | module OpenAttributeGraphCxx.C { 6 | umbrella header "OpenAttributeGraph/OpenAttributeGraph-umbrella.h" 7 | export * 8 | } 9 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCxxTests/Data/PageTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PageTests.swift 3 | // OpenAttributeGraphCxxTests 4 | 5 | #if canImport(Darwin) 6 | import OpenAttributeGraphCxx_Private.Data 7 | import Testing 8 | 9 | struct PageTests { 10 | 11 | } 12 | #endif 13 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Attribute/Body/AttributeBodyVisitor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AttributeBodyVisitor.swift 3 | // OpenAttributeGraph 4 | // 5 | // Status: WIP 6 | 7 | public protocol AttributeBodyVisitor { 8 | func visit(body: UnsafePointer) 9 | } 10 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 5 9 | patch: off 10 | # default: 11 | # target: auto 12 | # threshold: 5 13 | ignore: 14 | - Tests -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build* 3 | /Packages 4 | xcuserdata/ 5 | DerivedData/ 6 | .swiftpm/configuration/registries.json 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | .netrc 9 | coverage.txt 10 | TODO.md 11 | .ag_template/ 12 | build/ 13 | .ag_repo/ 14 | .oag_repo/ 15 | .claude 16 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/Focus.md: -------------------------------------------------------------------------------- 1 | # ``Focus`` 2 | 3 | ## Topics 4 | 5 | ### Creating Focus Rules 6 | 7 | - ``init(root:keyPath:)`` 8 | 9 | ### Properties 10 | 11 | - ``root`` 12 | - ``keyPath`` 13 | - ``value`` 14 | 15 | ### Configuration 16 | 17 | - ``flags`` 18 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/README.md: -------------------------------------------------------------------------------- 1 | ## OpenAttributeGraphCompatibilityTests 2 | 3 | Test public API of OpenAttributeGraph and run it against with AttributeGraph on Apple Platform. 4 | 5 | The current supported OS 6 | - macOS 14 (CI Supported) 7 | - iOS 15 ~ 17 on Simulator (CI is not supported) 8 | -------------------------------------------------------------------------------- /Scripts/CI/darwin_setup_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # A `realpath` alternative using the default C implementation. 4 | filepath() { 5 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 6 | } 7 | 8 | REPO_ROOT="$(dirname $(dirname $(dirname $(filepath $0))))" 9 | cd $REPO_ROOT 10 | 11 | Scripts/CI/ag_setup.sh -------------------------------------------------------------------------------- /Scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | # A `realpath` alternative using the default C implementation. 4 | filepath() { 5 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 6 | } 7 | 8 | OPENATTRIBUTEGRAPH_ROOT="$(dirname $(dirname $(filepath $0)))" 9 | 10 | cd $OPENATTRIBUTEGRAPH_ROOT 11 | 12 | swift build 13 | -------------------------------------------------------------------------------- /.github/workflows/issue-triage.yml: -------------------------------------------------------------------------------- 1 | name: Issue Triage 2 | 3 | on: 4 | issues: 5 | types: [opened] 6 | 7 | permissions: 8 | contents: read 9 | issues: write 10 | 11 | jobs: 12 | triage-issue: 13 | uses: OpenSwiftUIProject/github-workflows/.github/workflows/issue-triage.yml@main 14 | secrets: inherit 15 | -------------------------------------------------------------------------------- /.github/workflows/pr-triage.yml: -------------------------------------------------------------------------------- 1 | name: PR Triage 2 | 3 | on: 4 | pull_request: 5 | types: [opened] 6 | 7 | permissions: 8 | contents: read 9 | pull-requests: write 10 | 11 | jobs: 12 | triage-pr: 13 | uses: OpenSwiftUIProject/github-workflows/.github/workflows/pr-triage.yml@main 14 | secrets: inherit 15 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/StatefulRule.md: -------------------------------------------------------------------------------- 1 | # ``StatefulRule`` 2 | 3 | ## Topics 4 | 5 | ### Protocol Requirements 6 | 7 | - ``Value`` 8 | - ``initialValue`` 9 | - ``updateValue()`` 10 | 11 | ### Value Management 12 | 13 | - ``value`` 14 | - ``hasValue`` 15 | 16 | ### Context Access 17 | 18 | - ``attribute`` 19 | - ``context`` -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Rule/Rule.md: -------------------------------------------------------------------------------- 1 | # ``Rule`` 2 | 3 | ## Topics 4 | 5 | ### Protocol Requirements 6 | 7 | - ``Value`` 8 | - ``initialValue`` 9 | - ``value`` 10 | 11 | ### Context Access 12 | 13 | - ``attribute`` 14 | - ``context`` 15 | 16 | ### Cached Evaluation 17 | 18 | - ``cachedValue(options:owner:)`` 19 | - ``cachedValueIfExists(options:owner:)`` -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/Data/UniqueIDCompatibilityTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UniqueIDCompatibilityTests.swift 3 | // OpenAttributeGraphCompatibilityTests 4 | 5 | import Testing 6 | 7 | struct UniqueIDCompatibilityTests { 8 | @Test 9 | func uniqueID() throws { 10 | let initialID = makeUniqueID() 11 | #expect(makeUniqueID() == initialID + 1) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCxxTests/Data/ZoneTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ZoneTests.swift 3 | // OpenAttributeGraphCxxTests 4 | 5 | #if canImport(Darwin) 6 | import OpenAttributeGraphCxx_Private.Data 7 | import Testing 8 | 9 | struct ZoneTests { 10 | @Test 11 | func print() { 12 | // let zone = OAG.data.zone() 13 | // zone.print_header() 14 | // zone.print() 15 | } 16 | } 17 | #endif 18 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Data/OAGUniqueID.c: -------------------------------------------------------------------------------- 1 | // 2 | // OAGUniqueID.c 3 | // OpenAttributeGraphCxx 4 | // 5 | // Audited for 6.5.1 6 | // Status: Complete 7 | 8 | #include 9 | #include 10 | 11 | OAGUniqueID OAGMakeUniqueID(void) { 12 | static atomic_ulong counter = 1; 13 | return atomic_fetch_add_explicit(&counter, 1, memory_order_relaxed); 14 | } 15 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Graph/OAGGraphContext.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // OAGGraphContext.cpp 3 | // OpenAttributeGraphCxx 4 | 5 | #include 6 | #include 7 | 8 | OAGGraphRef OAGGraphContextGetGraph(OAGGraphContextRef context) { 9 | return reinterpret_cast(reinterpret_cast(context) - sizeof(CFRuntimeBase)); 10 | } 11 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCxxTests/Data/TableTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TableTests.swift 3 | // OpenAttributeGraphCxxTests 4 | 5 | #if canImport(Darwin) // table() is not implemented on Linux yet. 6 | import OpenAttributeGraphCxx_Private.Data 7 | import Testing 8 | 9 | struct TableTests { 10 | @Test 11 | func table() { 12 | let table = OAG.data.table() 13 | table.print() 14 | } 15 | } 16 | #endif 17 | -------------------------------------------------------------------------------- /Scripts/build_swiftinterface.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | # A `realpath` alternative using the default C implementation. 4 | filepath() { 5 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 6 | } 7 | 8 | OPENATTRIBUTEGRAPH_ROOT="$(dirname $(dirname $(filepath $0)))" 9 | 10 | cd $OPENATTRIBUTEGRAPH_ROOT 11 | 12 | swift build -Xswiftc -emit-module-interface -Xswiftc -enable-library-evolution -Xswiftc -no-verify-emitted-module-interface 13 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/Graph/GraphDescriptionCompatibilityTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GraphDescriptionCompatibilityTests.swift 3 | // OpenAttributeGraphCompatibilityTests 4 | 5 | import Testing 6 | 7 | #if canImport(Darwin) 8 | struct GraphDescriptionCompatibilityTests { 9 | @Test 10 | func format() { 11 | #expect(DescriptionOption.format.rawValue as String == "format") 12 | } 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Misc/assert.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // assert.hpp 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef assert_hpp 6 | #define assert_hpp 7 | 8 | #include 9 | 10 | namespace OAG { 11 | void precondition_failure(const char *format, ...) __cold __dead2; 12 | void non_fatal_precondition_failure(const char *format, ...); 13 | } /* OAG */ 14 | 15 | #endif /* assert_hpp */ 16 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Attribute/AttributeType.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // AttributeType.hpp 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef AttributeType_hpp 6 | #define AttributeType_hpp 7 | 8 | #include 9 | #include 10 | 11 | namespace OAG { 12 | struct AttributeType { 13 | OAGAttributeType storage; 14 | }; 15 | } 16 | #endif /* AttributeType_hpp */ 17 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/Attribute/Rule/RuleCompatibilityTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RuleCompatibilityTests.swift 3 | // OpenAttributeGraphCompatibilityTests 4 | 5 | import Testing 6 | 7 | struct RuleCompatibilityTests { 8 | @Test 9 | func ruleInitialValue() throws { 10 | struct A: Rule { 11 | typealias Value = Int 12 | var value: Int 13 | } 14 | #expect(A.initialValue == nil) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGInputOptions.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGInputOptions.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGInputOptions_h 6 | #define OAGInputOptions_h 7 | 8 | #include 9 | 10 | typedef OAG_OPTIONS(uint32_t, OAGInputOptions) { 11 | OAGInputOptionsNone = 0, 12 | OAGInputOptionsUnprefetched = 1 << 0, 13 | OAGInputOptionsSyncMainRef = 1 << 1, 14 | }; 15 | 16 | #endif /* OAGInputOptions_h */ 17 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Misc/env.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // env.hpp 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef env_hpp 6 | #define env_hpp 7 | 8 | #include 9 | 10 | namespace OAG { 11 | OAG_INLINE 12 | int get_env(const char *name) { 13 | char *value = getenv(name); 14 | if (value) { 15 | return atoi(value); 16 | } else { 17 | return 0; 18 | } 19 | } 20 | } 21 | 22 | #endif /* env_hpp */ 23 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleName 6 | OpenAttributeGraph 7 | CFBundleDisplayName 8 | OpenAttributeGraph 9 | CDDefaultCodeListingLanguage 10 | swift 11 | 12 | 13 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGChangedValueFlags.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGChangedValueFlags.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGChangedValueFlags_h 6 | #define OAGChangedValueFlags_h 7 | 8 | #include 9 | 10 | typedef OAG_OPTIONS(uint32_t, OAGChangedValueFlags) { 11 | OAGChangedValueFlagsChanged = 1 << 0, 12 | OAGChangedValueFlagsRequiresMainThread = 1 << 1, 13 | }; 14 | 15 | #endif /* OAGChangedValueFlags_h */ 16 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Misc/log.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // log.hpp 3 | // OpenAttributeGraphCxx 4 | // 5 | // Audited for 2021 Release 6 | 7 | #ifndef log_hpp 8 | #define log_hpp 9 | 10 | #include 11 | 12 | #if OAG_TARGET_OS_DARWIN 13 | 14 | #include 15 | 16 | namespace OAG { 17 | os_log_t misc_log(); 18 | os_log_t error_log(); 19 | } /* OAG */ 20 | 21 | #endif /* OAG_TARGET_OS_DARWIN */ 22 | 23 | #endif /* log_hpp */ 24 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGValue.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGValue.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGValue_h 6 | #define OAGValue_h 7 | 8 | #include 9 | #include 10 | 11 | OAG_ASSUME_NONNULL_BEGIN 12 | 13 | typedef struct OAGValue { 14 | const void *value; 15 | OAGChangedValueFlags flags; 16 | } OAGValue; 17 | 18 | OAG_ASSUME_NONNULL_END 19 | 20 | #endif /* OAGValue_h */ 21 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Runtime/metadata.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // metadata.cpp 3 | // OpenAttributeGraphCxx 4 | // 5 | // Audited for iOS 18.0 6 | // Status: WIP 7 | 8 | #include 9 | 10 | #ifdef OPENATTRIBUTEGRAPH_SWIFT_TOOLCHAIN_SUPPORTED 11 | 12 | using OAG::swift::metadata; 13 | 14 | void metadata::append_description(CFMutableStringRef description) const OAG_NOEXCEPT { 15 | // TODO 16 | } 17 | 18 | #endif /* OPENATTRIBUTEGRAPH_SWIFT_TOOLCHAIN_SUPPORTED */ 19 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Weak/WeakAttribute.md: -------------------------------------------------------------------------------- 1 | # ``WeakAttribute`` 2 | 3 | ## Topics 4 | 5 | ### Creating Weak Attributes 6 | 7 | - ``init()`` 8 | - ``init(base:)`` 9 | - ``init(_:)-4u8wa`` 10 | - ``init(_:)-571kb`` 11 | 12 | ### Property Wrapper 13 | 14 | - ``wrappedValue`` 15 | - ``projectedValue`` 16 | 17 | ### Dynamic Member Access 18 | 19 | - ``subscript(dynamicMember:)`` 20 | 21 | ### Value Access 22 | 23 | - ``attribute`` 24 | - ``value`` 25 | - ``changedValue(options:)`` -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGSearchOptions.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGSearchOptions.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGSearchOptions_h 6 | #define OAGSearchOptions_h 7 | 8 | #include 9 | 10 | typedef OAG_OPTIONS(uint32_t, OAGSearchOptions) { 11 | OAGSearchOptionsSearchInputs = 1 << 0, 12 | OAGSearchOptionsSearchOutputs = 1 << 1, 13 | OAGSearchOptionsTraverseGraphContexts = 1 << 2, 14 | } OAG_SWIFT_NAME(SearchOptions); 15 | 16 | #endif /* Header_h */ 17 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGWeakValue.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGWeakValue.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGWeakValue_h 6 | #define OAGWeakValue_h 7 | 8 | #include 9 | #include 10 | 11 | OAG_ASSUME_NONNULL_BEGIN 12 | 13 | typedef struct OAGWeakValue { 14 | const void * _Nullable value; 15 | OAGChangedValueFlags flags; 16 | } OAGWeakValue; 17 | 18 | OAG_ASSUME_NONNULL_END 19 | 20 | #endif /* OAGWeakValue_h */ 21 | -------------------------------------------------------------------------------- /.github/workflows/claude.yml: -------------------------------------------------------------------------------- 1 | name: Claude Code 2 | 3 | on: 4 | issue_comment: 5 | types: [created] 6 | pull_request_review_comment: 7 | types: [created] 8 | issues: 9 | types: [opened, assigned] 10 | pull_request_review: 11 | types: [submitted] 12 | 13 | permissions: 14 | contents: read 15 | pull-requests: read 16 | issues: read 17 | id-token: write 18 | actions: read 19 | 20 | jobs: 21 | claude: 22 | uses: OpenSwiftUIProject/github-workflows/.github/workflows/claude.yml@main 23 | secrets: inherit 24 | -------------------------------------------------------------------------------- /Docs/Status.md: -------------------------------------------------------------------------------- 1 | # Status Description 2 | 3 | Unless specified, the documentation is audited for 2023 release and the 4 | implementation is audited for iOS 15.5 5 | 6 | ## Empty 7 | 8 | Only have an empty namespace used as placeholder type in other implementation. 9 | 10 | ## WIP 11 | 12 | Some interface is implemented while some is not. 13 | 14 | ## Blocked 15 | 16 | Most implementation is complete. 17 | 18 | And some is commented/blocked due to other type's incompleteness. 19 | 20 | ## Complete 21 | 22 | All implementation is complete. 23 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGAttributeInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGAttributeInfo.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGAttributeInfo_h 6 | #define OAGAttributeInfo_h 7 | 8 | #include 9 | #include 10 | 11 | OAG_ASSUME_NONNULL_BEGIN 12 | 13 | typedef struct OAGAttributeInfo { 14 | const OAGAttributeType* type; 15 | const void *body; 16 | } OAGAttributeInfo; 17 | 18 | OAG_ASSUME_NONNULL_END 19 | 20 | #endif /* OAGAttributeInfo_h */ 21 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGUniqueID.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGUniqueID.h 3 | // OpenAttributeGraphCxx 4 | // 5 | // Audited for 6.5.1 6 | // Status: Complete 7 | 8 | #ifndef OAGUniqueID_h 9 | #define OAGUniqueID_h 10 | 11 | #include 12 | typedef u_long OAGUniqueID OAG_SWIFT_NAME(UniqueID); 13 | 14 | OAG_EXTERN_C_BEGIN 15 | OAG_EXPORT 16 | OAG_REFINED_FOR_SWIFT 17 | OAGUniqueID OAGMakeUniqueID(void) OAG_SWIFT_NAME(makeUniqueID()); 18 | OAG_EXTERN_C_END 19 | 20 | #endif /* OAGUniqueID_h */ 21 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Graph/OAGGraphTracing.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // OAGGraphTracing.mm 3 | // OpenAttributeGraphCxx 4 | 5 | #include 6 | 7 | void OAGGraphStartTracing(_Nullable OAGGraphRef graph, OAGGraphTraceOptions options) { 8 | OAGGraphStartTracing2(graph, options, NULL); 9 | } 10 | 11 | void OAGGraphStartTracing2(_Nullable OAGGraphRef graph, OAGGraphTraceOptions options, _Nullable CFArrayRef array) { 12 | // TODO 13 | } 14 | 15 | void OAGGraphStopTracing(_Nullable OAGGraphRef graph) { 16 | // TODO 17 | } 18 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Attribute/Body/ObservedAttribute.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ObservedAttribute.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: Complete 7 | 8 | public protocol ObservedAttribute: _AttributeBody { 9 | mutating func destroy() 10 | } 11 | 12 | extension ObservedAttribute { 13 | public static func _destroySelf(_ pointer: UnsafeMutableRawPointer) { 14 | pointer.assumingMemoryBound(to: Self.self).pointee.destroy() 15 | } 16 | 17 | public static var _hasDestroySelf: Bool { 18 | true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGAttributeFlags.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGAttributeFlags.h 3 | // OpenAttributeGraphCxx 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: Complete 7 | 8 | #ifndef OAGAttributeFlags_h 9 | #define OAGAttributeFlags_h 10 | 11 | #include 12 | #include 13 | 14 | typedef OAG_OPTIONS(uint8_t, OAGAttributeFlags) { 15 | OAGAttributeFlagsNone = 0, 16 | OAGAttributeFlagsAll = 0xFF, 17 | } OAG_SWIFT_NAME(OAGAttribute.Flags); 18 | 19 | #endif /* OAGAttributeFlags_h */ 20 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Data/page.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // page.hpp 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef page_hpp 6 | #define page_hpp 7 | 8 | #include 9 | #include 10 | 11 | namespace OAG { 12 | namespace data { 13 | 14 | class zone; 15 | template class ptr; 16 | 17 | struct page { 18 | zone *zone; 19 | ptr previous; 20 | uint32_t total; 21 | uint32_t in_use; 22 | }; /* page */ 23 | 24 | } /* data */ 25 | } /* OAG */ 26 | 27 | #endif /* page_hpp */ 28 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphShims/DebugServerMessageHeader.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DebugServerMessageHeader.swift 3 | // OpenAttributeGraphShims 4 | 5 | @_spi(Debug) 6 | public struct DebugServerMessageHeader { 7 | public let token: UInt32 8 | public let unknown: UInt32 9 | public let length: UInt32 10 | public let unknown2: UInt32 11 | 12 | public init(token: UInt32, unknown: UInt32, length: UInt32, unknown2: UInt32) { 13 | self.token = token 14 | self.unknown = unknown 15 | self.length = length 16 | self.unknown2 = unknown2 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/Attribute/Weak/WeakAttributeCompatibilityTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WeakAttributeCompatibilityTests.swift 3 | // OpenAttributeGraphCompatibilityTests 4 | 5 | import Testing 6 | 7 | #if canImport(Darwin) 8 | @MainActor 9 | @Suite(.enabled(if: compatibilityTestEnabled), .graphScope) 10 | struct WeakAttributeCompatibilityTests { 11 | @Test 12 | func initTest() { 13 | let _ = WeakAttribute() 14 | let _ = WeakAttribute(nil) 15 | let attr = Attribute(value: 0) 16 | let _ = WeakAttribute(attr) 17 | } 18 | } 19 | #endif 20 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Misc/log.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // OAGLog.cpp 3 | // OpenAttributeGraphCxx 4 | // 5 | // Audited for 2021 Release 6 | 7 | #include 8 | 9 | #if OAG_TARGET_OS_DARWIN 10 | 11 | namespace OAG { 12 | os_log_t misc_log() { 13 | static os_log_t log = os_log_create("org.OpenSwiftUIProject.OpenAttributeGraph", "misc"); 14 | return log; 15 | } 16 | os_log_t error_log() { 17 | static os_log_t log = os_log_create("org.OpenSwiftUIProject.OpenAttributeGraph", "error"); 18 | return log; 19 | } 20 | } /* OAG */ 21 | 22 | #endif /* OAG_TARGET_OS_DARWIN */ 23 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Attribute/OAGWeakAttribute.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // OAGWeakAttribute.cpp 3 | // OpenAttributeGraphCxx 4 | 5 | #include 6 | 7 | OAGWeakAttribute OAGCreateWeakAttribute(OAGAttribute attribute) { 8 | // TODO 9 | return {OAGAttributeNil , 0}; 10 | } 11 | 12 | OAGAttribute OAGWeakAttributeGetAttribute(OAGWeakAttribute weakAttribute) { 13 | // TODO 14 | return OAGAttributeNil; 15 | } 16 | 17 | OAGWeakValue OAGGraphGetWeakValue(OAGWeakAttribute weakAttribute, OAGValueOptions options, OAGTypeID type) { 18 | // TODO 19 | return {nullptr, false}; 20 | } 21 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGValueOptions.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGValueOptions.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGValueOptions_h 6 | #define OAGValueOptions_h 7 | 8 | #include 9 | 10 | typedef OAG_OPTIONS(uint32_t, OAGValueOptions) { 11 | OAGValueOptionsNone = 0, 12 | OAGValueOptionsInputOptionsUnprefetched = 1 << 0, 13 | OAGValueOptionsInputOptionsSyncMainRef = 1 << 1, 14 | OAGValueOptionsInputOptionsMask = 0x03, 15 | 16 | OAGValueOptionsIncrementGraphVersion = 1 << 2, // AsTopLevelOutput 17 | }; 18 | 19 | #endif /* OAGValueOptions_h */ 20 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGCachedValueOptions.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGCachedValueOptions.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGCachedValueOptions_h 6 | #define OAGCachedValueOptions_h 7 | 8 | #include 9 | 10 | typedef OAG_OPTIONS(uint32_t, OAGCachedValueOptions) { 11 | OAGCachedValueOptions_0 = 0, 12 | OAGCachedValueOptions_1 = 1 << 0, 13 | OAGCachedValueOptions_2 = 1 << 1, 14 | OAGCachedValueOptions_4 = 1 << 2, 15 | OAGCachedValueOptions_8 = 1 << 3, 16 | OAGCachedValueOptions_16 = 1 << 4, 17 | }; 18 | 19 | #endif /* OAGCachedValueOptions_h */ 20 | 21 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphTestsSupport/DataHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataHelper.swift 3 | // OpenAttributeGraphTestsSupport 4 | 5 | public struct Tuple { 6 | public var first: A 7 | public var second: B 8 | 9 | public init(first: A, second: B) { 10 | self.first = first 11 | self.second = second 12 | } 13 | } 14 | 15 | public struct Triple { 16 | public var first: A 17 | public var second: B 18 | public var third: C 19 | 20 | public init(first: A, second: B, third: C) { 21 | self.first = first 22 | self.second = second 23 | self.third = third 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGVersion.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGVersion.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGVersion_h 6 | #define OAGVersion_h 7 | 8 | #include 9 | 10 | #define OPENATTRIBUTEGRAPH_RELEASE 2024 11 | 12 | #define OPENATTRIBUTEGRAPH_RELEASE_2021 2021 13 | #define OPENATTRIBUTEGRAPH_RELEASE_2024 2024 14 | 15 | #ifndef OPENATTRIBUTEGRAPH_RELEASE 16 | #define OPENATTRIBUTEGRAPH_RELEASE OPENATTRIBUTEGRAPH_RELEASE_2024 17 | #endif 18 | 19 | OAG_EXTERN_C_BEGIN 20 | 21 | OAG_EXPORT const uint64_t OAGVersion; 22 | 23 | OAG_EXTERN_C_END 24 | 25 | #endif /* OAGVersion_h */ 26 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Data/page_const.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // page_const.hpp 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef page_const_hpp 6 | #define page_const_hpp 7 | 8 | #include 9 | 10 | namespace OAG { 11 | namespace data { 12 | 13 | constexpr const uint32_t page_mask_bits = 9; 14 | 15 | /// 0x200 16 | constexpr const uint32_t page_size = 1 << page_mask_bits; 17 | 18 | /// 0x1FF 19 | constexpr const uint32_t page_mask = page_size - 1; 20 | 21 | /// 0xFFFF_FE00 22 | constexpr const uintptr_t page_alignment = ~page_mask; 23 | 24 | } /* data */ 25 | } /* OAG */ 26 | 27 | 28 | #endif /* page_const_hpp */ 29 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Attribute/Rule/Map.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Map.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: Complete 7 | 8 | // MARK: - Map 9 | 10 | @frozen 11 | public struct Map: Rule, CustomStringConvertible { 12 | public var arg: Attribute 13 | public let body: (Source) -> Value 14 | 15 | public init(_ arg: Attribute, _ body: @escaping (Source) -> Value) { 16 | self.arg = arg 17 | self.body = body 18 | } 19 | 20 | public var value: Value { body(arg.value) } 21 | 22 | public static var flags: Flags { [] } 23 | 24 | public var description: String { "λ \(Value.self)" } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Runtime/OGTypeApplyEnumData.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OAGTypeApplyEnumData.swift 3 | // 4 | // 5 | // 6 | 7 | // public import OpenAttributeGraphCxx 8 | 9 | @discardableResult 10 | public func withUnsafePointerToEnumCase( 11 | of value: UnsafeMutablePointer, 12 | do body: (Int, Any.Type, UnsafeRawPointer) -> () 13 | ) -> Bool { 14 | // TODO: OAGTypeApplyEnumData 15 | return true 16 | } 17 | 18 | @discardableResult 19 | public func withUnsafeMutablePointerToEnumCase( 20 | of value: UnsafeMutablePointer, 21 | do body: (Int, Any.Type, UnsafeMutableRawPointer) -> () 22 | ) -> Bool { 23 | // TODO: OAGTypeApplyMutableEnumData 24 | return true 25 | } 26 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/Graph/GraphTracingCompatibilityTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GraphTracingCompatibilityTests.swift 3 | // OpenAttributeGraphCompatibilityTests 4 | 5 | import Testing 6 | 7 | struct GraphTracingCompatibilityTests { 8 | @Test 9 | func tracing() { 10 | let graph = Graph() 11 | Graph.startTracing(graph, options: []) 12 | Graph.stopTracing(graph) 13 | } 14 | 15 | @Test 16 | func tracingAll() { 17 | Graph.startTracing(nil, options: []) 18 | Graph.stopTracing(nil) 19 | } 20 | 21 | @Test 22 | func options() { 23 | let option = Graph.TraceOptions(rawValue: 1) 24 | #expect(option == .enabled) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Vector/realloc_vector.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // realloc_vector.hpp 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef realloc_vector_hpp 6 | #define realloc_vector_hpp 7 | 8 | #include 9 | 10 | OAG_ASSUME_NONNULL_BEGIN 11 | 12 | namespace OAG { 13 | namespace details { 14 | template 15 | void *_Nullable realloc_vector(void* ptr, T& size, T new_size); 16 | 17 | template 18 | void *_Nullable realloc_vector(void* src, void* dst, T dstSize, T& size, T newSize); 19 | } /* details */ 20 | } /* OAG */ 21 | 22 | OAG_ASSUME_NONNULL_END 23 | 24 | #endif /* realloc_vector_hpp */ 25 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGGraphContext.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGGraphContext.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGGraphContext_h 6 | #define OAGGraphContext_h 7 | 8 | #include 9 | #include 10 | 11 | // MARK: - Exported C functions 12 | 13 | OAG_ASSUME_NONNULL_BEGIN 14 | 15 | OAG_IMPLICIT_BRIDGING_ENABLED 16 | 17 | OAG_EXTERN_C_BEGIN 18 | 19 | OAG_EXPORT 20 | OAG_REFINED_FOR_SWIFT 21 | OAGGraphRef OAGGraphContextGetGraph(OAGGraphContextRef context) OAG_SWIFT_NAME(getter:OAGGraphContextRef.graph(self:)); 22 | 23 | OAG_EXTERN_C_END 24 | 25 | OAG_IMPLICIT_BRIDGING_DISABLED 26 | 27 | OAG_ASSUME_NONNULL_END 28 | 29 | #endif /* OAGGraphContext_h */ 30 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Attribute/Attribute/External.swift: -------------------------------------------------------------------------------- 1 | // 2 | // External.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: Complete 7 | 8 | @frozen 9 | public struct External { 10 | public init() {} 11 | } 12 | 13 | // MARK: - _AttributeBody 14 | 15 | extension External: _AttributeBody { 16 | public static var comparisonMode: ComparisonMode { .equatableAlways } 17 | 18 | public static var flags: Flags { [] } 19 | 20 | public static func _update(_: UnsafeMutableRawPointer, attribute _: AnyAttribute) {} 21 | } 22 | 23 | // MARK: CustomStringConvertible 24 | 25 | extension External: CustomStringConvertible { 26 | public var description: String { Metadata(Value.self).description } 27 | } 28 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/Attribute/Indirect/IndirectAttributeCompatibilityTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IndirectAttributeCompatibilityTests.swift 3 | // OpenAttributeGraphCompatibilityTests 4 | 5 | import Testing 6 | 7 | #if canImport(Darwin) 8 | @MainActor 9 | @Suite(.disabled(if: !compatibilityTestEnabled, "IndirectAttribute is not implemented"), .graphScope) 10 | struct IndirectAttributeCompatibilityTests { 11 | @Test 12 | func basic() { 13 | let source = Attribute(value: 0) 14 | let indirect = IndirectAttribute(source: source) 15 | #expect(indirect.identifier != source.identifier) 16 | #expect(indirect.source.identifier == source.identifier) 17 | #expect(indirect.dependency == .init(rawValue: 0)) 18 | } 19 | } 20 | #endif 21 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Util/free_deleter.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // free_deleter.hpp 3 | // OpenAttributeGraphCxx 4 | // 5 | // Status: Complete 6 | // Modified based Compute code 7 | 8 | #ifndef OPENATTRIBUTEGRAPH_CXX_UTIL_FREE_DELETER_HPP 9 | #define OPENATTRIBUTEGRAPH_CXX_UTIL_FREE_DELETER_HPP 10 | 11 | #include 12 | 13 | OAG_ASSUME_NONNULL_BEGIN 14 | 15 | namespace util { 16 | 17 | class free_deleter { 18 | public: 19 | template void operator()(T *_Nullable ptr) { 20 | if (ptr) { 21 | free((void *)ptr); 22 | } 23 | } 24 | }; /* class free_deleter */ 25 | 26 | } /* namespace util */ 27 | 28 | OAG_ASSUME_NONNULL_END 29 | 30 | #endif /* OPENATTRIBUTEGRAPH_CXX_UTIL_FREE_DELETER_HPP */ 31 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGValueState.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGValueState.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGValueState_h 6 | #define OAGValueState_h 7 | 8 | #include 9 | 10 | OAG_ASSUME_NONNULL_BEGIN 11 | 12 | typedef OAG_OPTIONS(uint8_t, OAGValueState) { 13 | OAGValueStateNone = 0, 14 | OAGValueStateDirty = 1 << 0, 15 | OAGValueStatePending = 1 << 1, 16 | OAGValueStateUpdating = 1 << 2, 17 | OAGValueStateValueExists = 1 << 3, 18 | OAGValueStateMainThread = 1 << 4, 19 | OAGValueStateMainRef = 1 << 5, 20 | OAGValueStateRequiresMainThread = 1 << 6, 21 | OAGValueStateSelfModified = 1 << 7, 22 | } OAG_SWIFT_NAME(ValueState); 23 | 24 | OAG_ASSUME_NONNULL_END 25 | 26 | #endif /* OAGValueState_h */ 27 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "originHash" : "85b8b98548f9706d608d822f14ce150964ddcef4203ed67755ff177a3c433895", 3 | "pins" : [ 4 | { 5 | "identity" : "darwinprivateframeworks", 6 | "kind" : "remoteSourceControl", 7 | "location" : "https://github.com/OpenSwiftUIProject/DarwinPrivateFrameworks.git", 8 | "state" : { 9 | "branch" : "main", 10 | "revision" : "5eb0f26ea5a5bbd5068f6b3daf3a97dd3682b234" 11 | } 12 | }, 13 | { 14 | "identity" : "swift-numerics", 15 | "kind" : "remoteSourceControl", 16 | "location" : "https://github.com/apple/swift-numerics", 17 | "state" : { 18 | "revision" : "0a5bc04095a675662cf24757cc0640aa2204253b", 19 | "version" : "1.0.2" 20 | } 21 | } 22 | ], 23 | "version" : 3 24 | } 25 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Comparison/OAGComparisonPrivate.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGComparisonPrivate.h 3 | // OpenAttributeGraphCxx 4 | // 5 | // Audited for 6.5.1 6 | // Status: Complete 7 | 8 | #ifndef OAGComparisonPrivate_h 9 | #define OAGComparisonPrivate_h 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | OAG_ASSUME_NONNULL_BEGIN 16 | 17 | OAG_EXTERN_C_BEGIN 18 | 19 | typedef struct OAGComparisonStateStorage { 20 | const void *destination; 21 | const void *source; 22 | OAGFieldRange field_range; 23 | OAGTypeID field_type; 24 | } OAGComparisonStateStorage; 25 | 26 | OAG_EXTERN_C_END 27 | 28 | OAG_ASSUME_NONNULL_END 29 | 30 | #endif /* OAGComparisonPrivate_h */ 31 | 32 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Graph/GraphDescription.mm: -------------------------------------------------------------------------------- 1 | // 2 | // GraphDescription.mm 3 | // OpenAttributeGraphCxx 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #if OAG_OBJC_FOUNDATION 11 | 12 | #include 13 | 14 | const CFStringRef OAGDescriptionFormat = CFSTR("format"); 15 | const CFStringRef OAGDescriptionIncludeValues = CFSTR("include-values"); 16 | 17 | CFTypeRef OAG::Graph::description(const Graph * _Nullable graph, NSDictionary* dic) { 18 | // TODO 19 | // For "format": "graph/dict" - NSMutableDictionray 20 | // For "format": "graph/dot" - NSMutableString 21 | return NULL; 22 | } 23 | 24 | #endif /* OAG_OBJC_FOUNDATION */ 25 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/Attribute/Rule/MapCompatibilityTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MapCompatibilityTests.swift 3 | // OpenAttributeGraphCompatibilityTests 4 | 5 | import Testing 6 | 7 | @MainActor 8 | @Suite(.disabled(if: !compatibilityTestEnabled), .graphScope) 9 | struct MapCompatibilityTests { 10 | @Test 11 | func description() throws { 12 | let map = Map(.init(value: 2)) { $0.description } 13 | let map2 = Map(.init(value: 1)) { $0 + 2 } 14 | 15 | #expect(map.description == "λ String") 16 | #expect(map2.description == "λ Int") 17 | } 18 | 19 | @Test 20 | func value() throws { 21 | let map = Map(.init(value: 2)) { $0.description } 22 | let map2 = Map(.init(value: 1)) { $0 + 2 } 23 | 24 | #expect(map.value == "2") 25 | #expect(map2.value == 3) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/Attribute/Attribute/FocusCompatibilityTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FocusCompatibilityTests.swift 3 | // OpenAttributeGraphCompatibilityTests 4 | 5 | import Testing 6 | 7 | #if canImport(Darwin) 8 | @MainActor 9 | @Suite(.disabled(if: !compatibilityTestEnabled, "Attribute is not implemented"), .graphScope) 10 | struct FocusCompatibilityTests { 11 | struct Demo { 12 | var a: Int 13 | var b: Double 14 | } 15 | 16 | @Test 17 | func example() throws { 18 | let root = Attribute(value: Demo(a: 0, b: 1.0)) 19 | let type = Focus.self 20 | let focus = type.init(root: root, keyPath: \.a) 21 | let d = focus.description 22 | #expect(d == "• Int") 23 | #expect(focus.value == 0) 24 | #expect(type.flags == []) 25 | } 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGClosure.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGClosure.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGClosure_h 6 | #define OAGClosure_h 7 | 8 | #include 9 | 10 | OAG_ASSUME_NONNULL_BEGIN 11 | 12 | OAG_EXTERN_C_BEGIN 13 | 14 | typedef struct OAGClosureStorage { 15 | const void *thunk; 16 | const void *_Nullable context; 17 | } OAGClosureStorage OAG_SWIFT_NAME(_OAGClosureStorage); 18 | 19 | OAG_EXPORT 20 | OAG_REFINED_FOR_SWIFT 21 | OAGClosureStorage OAGRetainClosure(void (*thunk)(void *_Nullable context OAG_SWIFT_CONTEXT) OAG_SWIFT_CC(swift), 22 | void *_Nullable context); 23 | 24 | OAG_EXPORT 25 | OAG_REFINED_FOR_SWIFT 26 | void OAGReleaseClosure(OAGClosureStorage closure); 27 | 28 | OAG_EXTERN_C_END 29 | 30 | OAG_ASSUME_NONNULL_END 31 | 32 | #endif /* OAGClosure_h */ 33 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphShims/GraphShims.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GraphShims.swift 3 | // OpenAttributeGraphShims 4 | 5 | #if OPENATTRIBUTEGRAPH_ATTRIBUTEGRAPH 6 | @_exported public import AttributeGraph 7 | public typealias OAGAttributeInfo = AGAttributeInfo 8 | public typealias OAGCachedValueOptions = AGCachedValueOptions 9 | public typealias OAGChangedValueFlags = AGChangedValueFlags 10 | public typealias OAGInputOptions = AGInputOptions 11 | public typealias OAGValue = AGValue 12 | public typealias OAGValueOptions = AGValueOptions 13 | public let attributeGraphEnabled = true 14 | public let swiftToolchainSupported = true 15 | #else 16 | @_exported import OpenAttributeGraph 17 | public let attributeGraphEnabled = false 18 | #if OPENATTRIBUTEGRAPH_SWIFT_TOOLCHAIN_SUPPORTED 19 | public let swiftToolchainSupported = true 20 | #else 21 | public let swiftToolchainSupported = false 22 | #endif 23 | #endif 24 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/OpenAttributeGraph.md: -------------------------------------------------------------------------------- 1 | # ``OpenAttributeGraph`` 2 | 3 | A high-performance reactive programming framework that powers OpenSwiftUI's underlying dependency tracking and update system. 4 | 5 | ## Overview 6 | 7 | It provides a reactive programming model built around attributes that automatically track dependencies and efficiently propagate changes through a dependency graph. 8 | 9 | The framework is designed for high performance and powers the reactive updates that make SwiftUI interfaces responsive and efficient. 10 | 11 | ## Topics 12 | 13 | ### Essentials 14 | 15 | - 16 | 17 | ### Attributes 18 | 19 | - 20 | - 21 | - 22 | 23 | ### Graph Management 24 | 25 | - 26 | 27 | ### Runtime Support 28 | 29 | - 30 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Version/OAGVersion.c: -------------------------------------------------------------------------------- 1 | // 2 | // OAGVersion.c 3 | // OpenAttributeGraph 4 | 5 | #include 6 | #include 7 | 8 | #if OPENATTRIBUTEGRAPH_RELEASE == OPENATTRIBUTEGRAPH_RELEASE_2024 9 | double OpenAttributeGraphVersionNumber __attribute__ ((used)) = (double)6.0; 10 | const unsigned char OpenAttributeGraphVersionString[] __attribute__ ((used)) = "@(#)PROAGRAM:OpenAttributeGraph PROJECT:OpenAttributeGraph-6.0.87\n"; 11 | const uint64_t OAGVersion = 0x2001e; 12 | #elif OPENATTRIBUTEGRAPH_RELEASE == OPENATTRIBUTEGRAPH_RELEASE_2021 13 | double OpenAttributeGraphVersionNumber __attribute__ ((used)) = (double)3.2; 14 | const unsigned char OpenAttributeGraphVersionString[] __attribute__ ((used)) = "@(#)PROAGRAM:OpenAttributeGraph PROJECT:OpenAttributeGraph-3.2.1\n"; 15 | const uint64_t OAGVersion = 0x20014; 16 | #endif 17 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/Attribute/Attribute/ExternalCompatibilityTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExternalCompatibilityTests.swift 3 | // OpenAttributeGraphCompatibilityTests 4 | 5 | import Testing 6 | 7 | // *** Program crashed: Bad pointer dereference at 0x0000000ffff9400a *** 8 | // swift-testing framework will crash here on Linux 9 | // Report to upstream for investigation when we bump to 5.10 10 | #if canImport(Darwin) 11 | @MainActor 12 | @Suite(.disabled(if: !compatibilityTestEnabled, "Attribute is not implemented"), .graphScope) 13 | struct ExternalCompatibilityTests { 14 | @Test 15 | func example() throws { 16 | let type = External.self 17 | let externalInt = type.init() 18 | #expect(externalInt.description == "Int") 19 | #expect(type.comparisonMode == .equatableAlways) 20 | #expect(type.flags == []) 21 | } 22 | } 23 | #endif 24 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/GraphShims.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GraphShims.swift 3 | // OpenAttributeGraphCompatibilityTests 4 | 5 | #if OPENATTRIBUTEGRAPH 6 | @_exported import OpenAttributeGraph 7 | let compatibilityTestEnabled = false 8 | #if OPENATTRIBUTEGRAPH_SWIFT_TOOLCHAIN_SUPPORTED 9 | public let swiftToolchainSupported = true 10 | #else 11 | public let swiftToolchainSupported = false 12 | #endif 13 | #else 14 | @_exported public import AttributeGraph 15 | public typealias OAGAttributeInfo = AGAttributeInfo 16 | public typealias OAGCachedValueOptions = AGCachedValueOptions 17 | public typealias OAGChangedValueFlags = AGChangedValueFlags 18 | public typealias OAGInputOptions = AGInputOptions 19 | public typealias OAGValue = AGValue 20 | public typealias OAGValueOptions = AGValueOptions 21 | public let compatibilityTestEnabled = true 22 | public let swiftToolchainSupported = true 23 | #endif 24 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGAttributeTypeFlags.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGAttributeTypeFlags.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGAttributeTypeFlags_h 6 | #define OAGAttributeTypeFlags_h 7 | 8 | #include 9 | 10 | typedef OAG_OPTIONS(uint32_t, OAGAttributeTypeFlags) { 11 | OAGAttributeTypeFlagsComparisonModeBitwise = 0, 12 | OAGAttributeTypeFlagsComparisonModeIndirect = 1, 13 | OAGAttributeTypeFlagsComparisonModeEquatableUnlessPOD = 2, 14 | OAGAttributeTypeFlagsComparisonModeEquatableAlways = 3, 15 | OAGAttributeTypeFlagsComparisonModeMask = 0x03, 16 | 17 | OAGAttributeTypeFlagsHasDestroySelf = 1 << 2, 18 | OAGAttributeTypeFlagsMainThread = 1 << 3, 19 | OAGAttributeTypeFlagsExternal = 1 << 4, 20 | OAGAttributeTypeFlagsAsyncThread = 1 << 5, 21 | } OAG_SWIFT_NAME(OAGAttributeType.Flags); 22 | 23 | #endif /* OAGAttributeTypeFlags_h */ 24 | 25 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Graph/GraphContext.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // GraphContext.cpp 3 | // OpenAttributeGraphCxx 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | OAG::Graph::Context &OAG::Graph::Context::from_cf(OAGGraphRef storage) OAG_NOEXCEPT { 10 | if (storage->context.isInvalid()) { 11 | OAG::precondition_failure("invalidated graph"); 12 | } 13 | return storage->context; 14 | } 15 | 16 | OAG::Graph::Context::Context(OAG::Graph &graph) OAG_NOEXCEPT : 17 | _graph(&graph), 18 | _context(nullptr), 19 | _id(OAGMakeUniqueID()), 20 | _invalidation_callback(nullptr), 21 | _update_callback(nullptr) { 22 | // TODO 23 | } 24 | 25 | OAG::Graph::Context::~Context() OAG_NOEXCEPT { 26 | // TODO 27 | } 28 | 29 | const bool OAG::Graph::Context::thread_is_updating() const OAG_NOEXCEPT { 30 | return _graph->thread_is_updating() && _graph->is_context_updating(*this); 31 | } 32 | -------------------------------------------------------------------------------- /Scripts/CI/ag_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # A `realpath` alternative using the default C implementation. 4 | filepath() { 5 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 6 | } 7 | 8 | REPO_ROOT="$(dirname $(dirname $(dirname $(filepath $0))))" 9 | 10 | clone_checkout_ag() { 11 | cd $REPO_ROOT 12 | revision=$(Scripts/CI/get_revision.sh darwinprivateframeworks) 13 | cd .. 14 | if [ ! -d DarwinPrivateFrameworks ]; then 15 | gh repo clone OpenSwiftUIProject/DarwinPrivateFrameworks 16 | cd DarwinPrivateFrameworks 17 | else 18 | echo "DarwinPrivateFrameworks already exists, skipping clone." 19 | cd DarwinPrivateFrameworks 20 | git fetch --all --quiet 21 | git stash --quiet || true 22 | git reset --hard --quiet origin/main 23 | fi 24 | git checkout --quiet $revision 25 | } 26 | 27 | update_ag() { 28 | cd $REPO_ROOT/../DarwinPrivateFrameworks 29 | swift package update-xcframeworks --allow-writing-to-package-directory 30 | } 31 | 32 | clone_checkout_ag 33 | update_ag 34 | -------------------------------------------------------------------------------- /Scripts/demangle.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | 4 | # A `realpath` alternative using the default C implementation. 5 | filepath() { 6 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 7 | } 8 | 9 | OAG_ROOT="$(dirname $(dirname $(filepath $0)))" 10 | 11 | # Get the language and input file path from the arguments 12 | language=${1:-"swift"} 13 | input_file=${2:-"$(dirname $(filepath $0))/demangle.txt"} 14 | 15 | echo "Demangling $input_file using $language mode" 16 | 17 | # Read each line of the input file 18 | while IFS= read -r line; do 19 | # Demangle the line using the appropriate tool based on the language 20 | if [[ $language == "swift" ]]; then 21 | xcrun swift-demangle "$line" 22 | elif [[ $language == "c++" ]]; then 23 | c++filt "$line" 24 | else 25 | echo "Invalid language: $language" 26 | echo "Usage: demangle.sh " 27 | echo "language: swift or c++, [default]: swift" 28 | echo "input file: [default] demangle.txt" 29 | exit 1 30 | fi 31 | done < "$input_file" 32 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/DebugServer/OAGDebugServer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // OAGDebugServer.cpp 3 | // OpenAttributeGraphCxx 4 | // 5 | // Audited for 6.5.1 6 | // Status: Complete 7 | 8 | #include 9 | #include 10 | 11 | #if OAG_TARGET_OS_DARWIN 12 | 13 | // MARK: - Exported C functions 14 | 15 | OAGDebugServerRef _Nullable OAGDebugServerStart(OAGDebugServerMode port) { 16 | return (OAGDebugServerRef)OAG::DebugServer::start(port); 17 | } 18 | 19 | void OAGDebugServerStop() { 20 | OAG::DebugServer::stop(); 21 | } 22 | 23 | CFURLRef _Nullable OAGDebugServerCopyURL() { 24 | if (!OAG::DebugServer::has_shared_server()) { 25 | return nullptr; 26 | } 27 | return OAG::DebugServer::shared_server()->copy_url(); 28 | } 29 | 30 | void OAGDebugServerRun(int timeout) { 31 | if (!OAG::DebugServer::has_shared_server()) { 32 | return; 33 | } 34 | OAG::DebugServer::shared_server()->run(timeout); 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGGraphCounterQueryType.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGGraphCounterQueryType.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGGraphCounterQueryType_h 6 | #define OAGGraphCounterQueryType_h 7 | 8 | #include 9 | 10 | typedef OAG_ENUM(uint32_t, OAGGraphCounterQueryType) { 11 | OAGGraphCounterQueryTypeNodes, 12 | OAGGraphCounterQueryTypeTransactions, 13 | OAGGraphCounterQueryTypeUpdates, 14 | OAGGraphCounterQueryTypeChanges, 15 | OAGGraphCounterQueryTypeContextID, 16 | OAGGraphCounterQueryTypeGraphID, 17 | OAGGraphCounterQueryTypeContextThreadUpdating, 18 | OAGGraphCounterQueryTypeThreadUpdating, 19 | OAGGraphCounterQueryTypeContextNeedsUpdate, 20 | OAGGraphCounterQueryTypeNeedsUpdate, 21 | OAGGraphCounterQueryTypeMainThreadUpdates, 22 | OAGGraphCounterQueryTypeCreatedNodes, 23 | OAGGraphCounterQueryTypeSubgraphs, 24 | OAGGraphCounterQueryTypeCreatedSubgraphs, 25 | } OAG_SWIFT_NAME(OAGGraphRef.CounterQueryType); 26 | 27 | #endif /* OAGGraphCounterQueryType_h */ 28 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGWeakAttribute.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGWeakAttribute.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGWeakAttribute_hpp 6 | #define OAGWeakAttribute_hpp 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | OAG_ASSUME_NONNULL_BEGIN 13 | 14 | typedef OAG_SWIFT_STRUCT struct { 15 | struct { 16 | OAGAttribute identifier; 17 | uint32_t seed; 18 | } _details; 19 | } OAGWeakAttribute OAG_SWIFT_NAME(AnyWeakAttribute); 20 | 21 | OAG_EXTERN_C_BEGIN 22 | 23 | OAG_EXPORT 24 | OAG_REFINED_FOR_SWIFT 25 | OAGWeakAttribute OAGCreateWeakAttribute(OAGAttribute attribute); 26 | 27 | OAG_EXPORT 28 | OAG_REFINED_FOR_SWIFT 29 | OAGAttribute OAGWeakAttributeGetAttribute(OAGWeakAttribute weakAttribute); 30 | 31 | OAG_EXPORT 32 | OAG_REFINED_FOR_SWIFT 33 | OAGWeakValue OAGGraphGetWeakValue(OAGWeakAttribute weakAttribute, OAGValueOptions options, OAGTypeID type); 34 | 35 | OAG_EXTERN_C_END 36 | 37 | OAG_ASSUME_NONNULL_END 38 | 39 | #endif /* OAGWeakAttribute_h */ 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023-2025 Kyle-Ye 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphTestsSupport/GraphEnvironmentTrait.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GraphEnvironmentTrait.swift 3 | // OpenAttributeGraphTestsSupport 4 | 5 | public import Testing 6 | 7 | public struct GraphEnvironmentTrait: TestTrait, TestScoping, SuiteTrait { 8 | private static let sharedGraph = Graph() 9 | private static let semaphore = AsyncSemaphore(value: 1) 10 | 11 | @MainActor 12 | public func provideScope(for test: Test, testCase: Test.Case?, performing function: @Sendable () async throws -> Void) async throws { 13 | await Self.semaphore.wait() 14 | defer { Self.semaphore.signal() } 15 | let graph = Graph(shared: Self.sharedGraph) 16 | let subgraph = Subgraph(graph: graph) 17 | let oldSubgraph = Subgraph.current 18 | 19 | Subgraph.current = subgraph 20 | try await function() 21 | Subgraph.current = oldSubgraph 22 | } 23 | 24 | public var isRecursive: Bool { 25 | true 26 | } 27 | } 28 | 29 | extension Trait where Self == GraphEnvironmentTrait { 30 | public static var graphScope: Self { 31 | GraphEnvironmentTrait() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Graph/GraphDescription.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // GraphDescription.cpp 3 | // OpenAttributeGraphCxx 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | CFTypeRef OAGGraphDescription(OAGGraphRef graph, CFDictionaryRef options) { 11 | #if OAG_OBJC_FOUNDATION 12 | if (graph == nullptr) { 13 | return OAG::Graph::description(nullptr, (__bridge NSDictionary*)options); 14 | } 15 | if (graph->context.isInvalid()) { 16 | OAG::precondition_failure("invalidated graph"); 17 | } 18 | return OAG::Graph::description(&graph->context.get_graph(), (__bridge NSDictionary*)options); 19 | #endif 20 | } 21 | 22 | void OAGGraphArchiveJSON(char const * _Nullable name) { 23 | #if OAG_OBJC_FOUNDATION 24 | OAG::Graph::write_to_file(nullptr, name, 0); 25 | #endif 26 | } 27 | 28 | void OAGGraphArchiveJSON2(char const * _Nullable name, uint8_t options) { 29 | #if OAG_OBJC_FOUNDATION 30 | OAG::Graph::write_to_file(nullptr, name, options); 31 | #endif 32 | } 33 | 34 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphShims/Graph+Debug.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Graph+Debug.swift 3 | // OpenAttributeGraphShims 4 | 5 | #if canImport(Darwin) 6 | 7 | import Foundation 8 | 9 | @_spi(Debug) 10 | extension Graph { 11 | public var dict: [String: Any]? { 12 | let options = [ 13 | DescriptionOption.format: Graph.descriptionFormatDictionary 14 | ] as NSDictionary 15 | guard let description = Graph.description(nil, options: options) else { 16 | return nil 17 | } 18 | guard let dictionary = description as? NSDictionary else { 19 | return nil 20 | } 21 | return dictionary as? [String: Any] 22 | } 23 | 24 | // style: 25 | // - bold: empty input/output edge 26 | // - dashed: indirect or has no value 27 | // color: 28 | // - red: is_changed 29 | public var dot: String? { 30 | let options = [ 31 | DescriptionOption.format: Graph.descriptionFormatDot 32 | ] as NSDictionary 33 | guard let description = Graph.description(self, options: options) 34 | else { 35 | return nil 36 | } 37 | return description as? String 38 | } 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Runtime/CompareValues.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CompareValues.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: Complete 7 | 8 | public import OpenAttributeGraphCxx 9 | 10 | @_silgen_name("OAGCompareValues") 11 | private func OAGCompareValues( 12 | lhs: UnsafeRawPointer, 13 | rhs: UnsafeRawPointer, 14 | type: Any.Type, 15 | options: ComparisonOptions 16 | ) -> Bool 17 | 18 | /// Compares two values using the specified comparison mode. 19 | public func compareValues(_ lhs: Value, _ rhs: Value, mode: ComparisonMode = .equatableAlways) -> Bool { 20 | compareValues(lhs, rhs, options: [.init(mode: mode), .copyOnWrite]) 21 | } 22 | 23 | /// Compares two values using the specified comparison options. 24 | public func compareValues(_ lhs: Value, _ rhs: Value, options: ComparisonOptions) -> Bool { 25 | withUnsafePointer(to: lhs) { p1 in 26 | withUnsafePointer(to: rhs) { p2 in 27 | OAGCompareValues(lhs: p1, rhs: p2, type: Value.self, options: options) 28 | } 29 | } 30 | } 31 | 32 | extension ComparisonOptions { 33 | public init(mode: ComparisonMode) { 34 | self.init(rawValue: numericCast(mode.rawValue)) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Reactive-Attributes.md: -------------------------------------------------------------------------------- 1 | # Reactive Attributes 2 | 3 | Reactive properties that automatically track dependencies and manage value updates. 4 | 5 | ## Overview 6 | 7 | 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. 8 | 9 | The primary reactive attribute types provide different levels of memory management and reference semantics to handle various use cases in reactive applications. 10 | 11 | ## Topics 12 | 13 | ### Core Reactive Types 14 | 15 | - ``Attribute`` 16 | - ``WeakAttribute`` 17 | - ``OptionalAttribute`` 18 | 19 | ### Property Wrapper Support 20 | 21 | - ``Attribute/wrappedValue`` 22 | - ``Attribute/projectedValue`` 23 | - ``WeakAttribute/wrappedValue`` 24 | - ``WeakAttribute/projectedValue`` 25 | 26 | ### Dynamic Member Access 27 | 28 | - ``Attribute/subscript(dynamicMember:)`` 29 | - ``WeakAttribute/subscript(dynamicMember:)`` 30 | 31 | ### Value Management 32 | 33 | - ``Attribute/value`` 34 | - ``Attribute/setValue(_:)`` 35 | - ``WeakAttribute/value`` 36 | - ``WeakAttribute/changedValue(options:)`` -------------------------------------------------------------------------------- /Scripts/CI/get_revision.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script extracts the revision of a specific dependency from the Package.resolved file (Only support v3). 4 | # Usage: ./get_revision.sh 5 | # Output: revision of the dependency 6 | 7 | # A `realpath` alternative using the default C implementation. 8 | filepath() { 9 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 10 | } 11 | 12 | REPO_ROOT="$(dirname $(dirname $(dirname $(filepath $0))))" 13 | cd $REPO_ROOT 14 | 15 | # Ensure a dependency name is provided as an argument 16 | if [[ $# -lt 1 ]]; then 17 | echo "Usage: $0 " 18 | exit 1 19 | fi 20 | 21 | DEPENDENCY_NAME="$1" 22 | PACKAGE_RESOLVED_PATH="Package.resolved" 23 | 24 | # Check if the Package.resolved file exists 25 | if [[ ! -f "$PACKAGE_RESOLVED_PATH" ]]; then 26 | echo "Error: $PACKAGE_RESOLVED_PATH file not found!" 27 | exit 1 28 | fi 29 | 30 | # Extract the revision using jq 31 | REVISION=$(jq -r --arg name "$DEPENDENCY_NAME" ' 32 | .pins[]? 33 | | select(.identity == $name) 34 | | .state.revision 35 | ' "$PACKAGE_RESOLVED_PATH") 36 | 37 | # Check if a revision was found 38 | if [[ -z "$REVISION" ]]; then 39 | echo "No revision found for dependency: $DEPENDENCY_NAME" 40 | exit 1 41 | else 42 | echo "$REVISION" 43 | fi -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/DebugServer/interpose.c: -------------------------------------------------------------------------------- 1 | // 2 | // interpose.c 3 | // OpenAttributeGraphCxx 4 | 5 | #include 6 | #include "stdio.h" 7 | #include "stdbool.h" 8 | #include "string.h" 9 | 10 | #if OAG_TARGET_OS_DARWIN 11 | extern bool os_variant_has_internal_diagnostics(const char *subsystem); 12 | #endif 13 | 14 | bool oag_variant_has_internal_diagnostics(const char *subsystem) { 15 | if (strcmp(subsystem, "org.OpenSwiftUIProject.OpenAttributeGraph") == 0) { 16 | return true; 17 | } else if (strcmp(subsystem, "com.apple.AttributeGraph") == 0) { 18 | return true; 19 | } else { 20 | #if OAG_TARGET_OS_DARWIN 21 | return os_variant_has_internal_diagnostics(subsystem); 22 | #else 23 | return false; 24 | #endif 25 | } 26 | } 27 | 28 | #if OAG_TARGET_OS_DARWIN 29 | #define DYLD_INTERPOSE(_replacement,_replacee) \ 30 | __attribute__((used)) static struct{ const void* replacement; const void* replacee; } _interpose_##_replacee \ 31 | __attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacement, (const void*)(unsigned long)&_replacee }; 32 | 33 | DYLD_INTERPOSE(oag_variant_has_internal_diagnostics, os_variant_has_internal_diagnostics) 34 | #endif 35 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Attribute/Body/AttributeBody.swift: -------------------------------------------------------------------------------- 1 | // 2 | // _AttributeBody.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: Complete 7 | 8 | public import OpenAttributeGraphCxx 9 | 10 | public protocol _AttributeBody { 11 | static func _destroySelf(_ pointer: UnsafeMutableRawPointer) 12 | static var _hasDestroySelf: Bool { get } 13 | static func _updateDefault(_ pointer: UnsafeMutableRawPointer) 14 | static var comparisonMode: ComparisonMode { get } 15 | typealias Flags = _AttributeType.Flags 16 | static var flags: Flags { get } 17 | } 18 | 19 | // MARK: - Protocol Default implementation 20 | 21 | extension _AttributeBody { 22 | public static func _destroySelf(_ pointer: UnsafeMutableRawPointer) {} 23 | public static var _hasDestroySelf: Bool { false } 24 | public static func _updateDefault(_ pointer: UnsafeMutableRawPointer) {} 25 | public static var comparisonMode: ComparisonMode { .equatableUnlessPOD } 26 | public static var flags: Flags { .mainThread } 27 | } 28 | 29 | extension _AttributeBody { 30 | static func _visitBody(_ visitor: inout Visitor, _ body: UnsafeRawPointer) { 31 | visitor.visit(body: body.assumingMemoryBound(to: Self.self)) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Attribute/Attribute.md: -------------------------------------------------------------------------------- 1 | # ``Attribute`` 2 | 3 | ## Topics 4 | 5 | ### Creating Attributes 6 | 7 | - ``init(identifier:)`` 8 | - ``init(_:)`` 9 | - ``init(value:)`` 10 | - ``init(type:)`` 11 | 12 | ### Property Wrapper 13 | 14 | - ``wrappedValue`` 15 | - ``projectedValue`` 16 | 17 | ### Dynamic Member Access 18 | 19 | - ``subscript(dynamicMember:)`` 20 | - ``subscript(keyPath:)`` 21 | - ``subscript(offset:)`` 22 | 23 | ### Type Transformations 24 | 25 | - ``unsafeCast(to:)`` 26 | - ``unsafeOffset(at:as:)`` 27 | - ``applying(offset:)`` 28 | 29 | ### Graph Integration 30 | 31 | - ``graph`` 32 | - ``subgraph`` 33 | 34 | ### Value Management 35 | 36 | - ``value`` 37 | - ``valueState`` 38 | - ``valueAndFlags(options:)`` 39 | - ``changedValue(options:)`` 40 | - ``setValue(_:)`` 41 | - ``hasValue`` 42 | - ``updateValue()`` 43 | - ``prefetchValue()`` 44 | - ``invalidateValue()`` 45 | - ``validate()`` 46 | 47 | ### Input Management 48 | 49 | - ``addInput(_:options:token:)-9c3h6`` 50 | - ``addInput(_:options:token:)-7u9k3`` 51 | 52 | ### Flags and State 53 | 54 | - ``Flags`` 55 | - ``flags`` 56 | - ``setFlags(_:mask:)`` 57 | 58 | ### Advanced Operations 59 | 60 | - ``visitBody(_:)`` 61 | - ``mutateBody(as:invalidating:_:)`` 62 | - ``breadthFirstSearch(options:_:)`` -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/UnsafeTuple.md: -------------------------------------------------------------------------------- 1 | # ``UnsafeTuple`` 2 | 3 | Immutable tuple buffer for safe element access and type-checked operations. 4 | 5 | ## Overview 6 | 7 | `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. 8 | 9 | withUnsafeTuple(of: tupleType, count: 1) { unsafeTuple in 10 | let firstElement: Int = unsafeTuple[0] 11 | let secondElement: String = unsafeTuple[1] 12 | // Access elements safely with compile-time type checking 13 | } 14 | 15 | ## Key Features 16 | 17 | - Type-safe element access: Access tuple elements with automatic type verification 18 | - Index-based operations: Use integer indices to access elements by position 19 | - Memory safety: Bounds checking and type validation prevent unsafe memory access 20 | - Address computation: Get typed pointers to specific tuple elements 21 | 22 | ## Topics 23 | 24 | ### Tuple Properties 25 | 26 | - ``count`` 27 | - ``isEmpty`` 28 | - ``indices`` 29 | 30 | ### Element Access 31 | 32 | - ``subscript()`` 33 | - ``subscript(_:)`` 34 | 35 | ### Address Operations 36 | 37 | - ``address(as:)`` 38 | - ``address(of:as:)`` -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Computed-Attributes.md: -------------------------------------------------------------------------------- 1 | # Computed Attributes 2 | 3 | Rule-based attributes that compute their values from other attributes. 4 | 5 | ## Overview 6 | 7 | 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. 8 | 9 | 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. 10 | 11 | ## Topics 12 | 13 | ### Rule Protocols 14 | 15 | - ``Rule`` 16 | - ``StatefulRule`` 17 | - ``_AttributeBody`` 18 | 19 | ### Specialized Rules 20 | 21 | - ``Focus`` 22 | - ``External`` 23 | 24 | ### Rule Creation 25 | 26 | - ``Attribute/init(_:)-4tj1v`` 27 | - ``Attribute/init(_:)-8hz0z`` 28 | - ``Focus/init(root:keyPath:)`` 29 | 30 | ### Rule Properties 31 | 32 | - ``Rule/value`` 33 | - ``Rule/flags`` 34 | - ``StatefulRule/value`` 35 | - ``StatefulRule/flags`` 36 | - ``Focus/root`` 37 | - ``Focus/keyPath`` 38 | - ``Focus/value`` 39 | 40 | ### Update Mechanisms 41 | 42 | - ``Rule/_update`` 43 | - ``StatefulRule/_update`` -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/Metadata.md: -------------------------------------------------------------------------------- 1 | # ``Metadata`` 2 | 3 | Swift runtime type information and reflection capabilities for OpenAttributeGraph. 4 | 5 | ## Overview 6 | 7 | `Metadata` provides access to Swift's runtime type system, enabling type introspection and dynamic operations that power OpenAttributeGraph's reactive system. 8 | 9 | let intMetadata = Metadata(Int.self) 10 | let stringMetadata = Metadata(String.self) 11 | 12 | let metadata = Metadata(String.self) 13 | let type = metadata.type // Returns String.Type 14 | 15 | ## Key Features 16 | 17 | - Runtime type introspection: Access Swift type metadata at runtime 18 | - Field enumeration: Discover the fields of any Swift type 19 | - Type comparison: Efficient equality checking across different types 20 | - Memory layout: Access memory layout and alignment details 21 | 22 | ## Usage with Attributes 23 | 24 | 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. 25 | 26 | ## Topics 27 | 28 | ### Creating Metadata 29 | 30 | - ``init(_:)`` 31 | 32 | ### Type Information 33 | 34 | - ``type`` 35 | - ``description`` 36 | 37 | ### Field Introspection 38 | 39 | - ``forEachField(options:do:)`` 40 | 41 | ### Global Functions 42 | 43 | - ``forEachField(of:do:)`` -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGSwiftSupport.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGSwiftSupport.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGSwiftSupport_h 6 | #define OAGSwiftSupport_h 7 | 8 | #if __has_attribute(swift_name) 9 | #define OAG_SWIFT_NAME(_name) __attribute__((swift_name(#_name))) 10 | #else 11 | #define OAG_SWIFT_NAME 12 | #endif 13 | 14 | #if __has_attribute(swift_wrapper) 15 | #define OAG_SWIFT_STRUCT __attribute__((swift_wrapper(struct))) 16 | #else 17 | #define OAG_SWIFT_STRUCT 18 | #endif 19 | 20 | #if __has_attribute(swift_private) 21 | #define OAG_REFINED_FOR_SWIFT __attribute__((swift_private)) 22 | #else 23 | #define OAG_REFINED_FOR_SWIFT 24 | #endif 25 | 26 | // MARK: - Call Convension 27 | 28 | #define OAG_SWIFT_CC(CC) OAG_SWIFT_CC_##CC 29 | // OAG_SWIFT_CC(c) is the C calling convention. 30 | #define OAG_SWIFT_CC_c 31 | 32 | // OAG_SWIFT_CC(swift) is the Swift calling convention. 33 | #if __has_attribute(swiftcall) 34 | #define OAG_SWIFT_CC_swift __attribute__((swiftcall)) 35 | #define OAG_SWIFT_CONTEXT __attribute__((swift_context)) 36 | #define OAG_SWIFT_ERROR_RESULT __attribute__((swift_error_result)) 37 | #define OAG_SWIFT_INDIRECT_RESULT __attribute__((swift_indirect_result)) 38 | #else 39 | #define OAG_SWIFT_CC_swift 40 | #define OAG_SWIFT_CONTEXT 41 | #define OAG_SWIFT_ERROR_RESULT 42 | #define OAG_SWIFT_INDIRECT_RESULT 43 | #endif 44 | 45 | #endif /* OAGSwiftSupport_h */ 46 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Comparison/OAGComparison.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // OAGCompareValues.cpp 3 | // OpenAttributeGraphCxx 4 | 5 | #include 6 | #include 7 | 8 | const void *OAGComparisonStateGetDestination(OAGComparisonState state) { 9 | return ((const OAGComparisonStateStorage *)state)->destination; 10 | } 11 | 12 | const void *OAGComparisonStateGetSource(OAGComparisonState state) { 13 | return ((const OAGComparisonStateStorage *)state)->source; 14 | } 15 | 16 | OAGFieldRange OAGComparisonStateGetFieldRange(OAGComparisonState state) { 17 | return ((const OAGComparisonStateStorage *)state)->field_range; 18 | } 19 | 20 | OAGTypeID OAGComparisonStateGetFieldType(OAGComparisonState state) { 21 | return ((const OAGComparisonStateStorage *)state)->field_type; 22 | } 23 | 24 | bool OAGCompareValues(const void *lhs, const void *rhs, OAGTypeID type, OAGComparisonOptions options) { 25 | // TODO 26 | return false; 27 | } 28 | 29 | const unsigned char *_Nullable OAGPrefetchCompareValues(OAGTypeID type_id, 30 | OAGComparisonOptions options, 31 | uint32_t priority) { 32 | // TODO 33 | return nullptr; 34 | } 35 | 36 | void OAGOverrideComparisonForTypeDescriptor(void *descriptor, OAGComparisonMode mode) { 37 | // TODO 38 | } 39 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph/Subgraph.md: -------------------------------------------------------------------------------- 1 | # ``Subgraph`` 2 | 3 | Scoped computation contexts for isolated attribute groups. 4 | 5 | ## Overview 6 | 7 | `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. 8 | 9 | Subgraphs are essential for organizing complex attribute hierarchies and controlling the scope of reactive updates. 10 | 11 | ## Key Features 12 | 13 | - Isolation: Separate update domains for different parts of your application 14 | - Performance: Smaller update scopes reduce computational overhead 15 | - Testing: Isolated environments for unit testing 16 | - Observer pattern: Add observers for subgraph changes 17 | 18 | ## Usage Pattern 19 | 20 | Subgraphs are commonly used to: 21 | - Isolate different UI components or modules 22 | - Create test environments with controlled attribute scopes 23 | - Optimize performance by limiting update propagation 24 | - Implement hierarchical reactive systems 25 | 26 | ## Topics 27 | 28 | ### Type Aliases 29 | 30 | - ``Flags`` 31 | - ``ChildFlags`` 32 | 33 | ### Observers 34 | 35 | - ``addObserver(_:)`` 36 | 37 | ### Scoped Execution 38 | 39 | - ``apply(_:)`` 40 | 41 | ### Attribute Iteration 42 | 43 | - ``forEach(_:_:)`` 44 | 45 | ### Global Access 46 | 47 | - ``current`` 48 | - ``currentGraphContext`` -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Attribute-References.md: -------------------------------------------------------------------------------- 1 | # Attribute References 2 | 3 | Type-erased and reference management for attributes. 4 | 5 | ## Overview 6 | 7 | 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. 8 | 9 | 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. 10 | 11 | ## Topics 12 | 13 | ### Type-Erased References 14 | 15 | - ``AnyAttribute`` 16 | 17 | ### Reference Creation 18 | 19 | - ``AnyAttribute/init(_:)`` 20 | - ``Attribute/init(identifier:)`` 21 | 22 | ### Reference Operations 23 | 24 | - ``AnyAttribute/unsafeCast(to:)`` 25 | - ``Attribute/unsafeCast(to:)`` 26 | - ``AnyAttribute/create(offset:size:)`` 27 | 28 | ### Reference Properties 29 | 30 | - ``AnyAttribute/identifier`` 31 | - ``Attribute/identifier`` 32 | 33 | ### Memory Management 34 | 35 | - ``AnyAttribute/graph`` 36 | - ``AnyAttribute/subgraph`` 37 | - ``Attribute/graph`` 38 | - ``Attribute/subgraph`` 39 | 40 | ### Value State 41 | 42 | - ``AnyAttribute/valueState`` 43 | - ``Attribute/valueState`` 44 | - ``AnyAttribute/hasValue`` 45 | - ``Attribute/hasValue`` -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/VersionCompatibilityTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VersionCompatibilityTests.swift 3 | // OpenAttributeGraphCompatibilityTests 4 | 5 | import Testing 6 | import Numerics 7 | 8 | struct VersionTests { 9 | @Test 10 | func versionNumber() async { 11 | await confirmation { confirm in 12 | #if OPENATTRIBUTEGRAPH 13 | switch Int32(OPENATTRIBUTEGRAPH_RELEASE) { 14 | case OPENATTRIBUTEGRAPH_RELEASE_2021: 15 | #expect(OpenAttributeGraphVersionNumber.isApproximatelyEqual(to: 3.2)) 16 | #expect(OAGVersion == 0x20014) 17 | confirm() 18 | case OPENATTRIBUTEGRAPH_RELEASE_2024: 19 | #expect(OpenAttributeGraphVersionNumber.isApproximatelyEqual(to: 6.0)) 20 | #expect(OAGVersion == 0x2001e) 21 | confirm() 22 | default: 23 | break 24 | } 25 | #else 26 | switch Int32(ATTRIBUTEGRAPH_RELEASE) { 27 | case ATTRIBUTEGRAPH_RELEASE_2021: 28 | #expect(AGVersion == 0x20014) 29 | confirm() 30 | case ATTRIBUTEGRAPH_RELEASE_2024: 31 | #expect(AGVersion == 0x2001e) 32 | confirm() 33 | default: 34 | break 35 | } 36 | #endif 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /.github/workflows/ubuntu.yml: -------------------------------------------------------------------------------- 1 | name: Ubuntu 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | ubuntu_test: 11 | name: Execute tests on Ubuntu 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | swift_version: ["6.1.2"] 16 | runs-on: ubuntu-22.04 17 | env: 18 | OPENATTRIBUTEGRAPH_WERROR: 1 19 | OPENATTRIBUTEGRAPH_ATTRIBUTEGRAPH: 0 20 | OPENATTRIBUTEGRAPH_COMPATIBILITY_TEST: 0 21 | container: swift:${{ matrix.swift_version }}-jammy 22 | steps: 23 | - uses: actions/checkout@v4 24 | - name: Swift version 25 | run: | 26 | which swift && swift --version 27 | - name: Building and running tests in debug mode with coverage 28 | run: | 29 | swift test \ 30 | -c debug \ 31 | --enable-code-coverage \ 32 | --build-path .build-test-debug 33 | llvm-cov show \ 34 | -instr-profile=.build-test-debug/debug/codecov/default.profdata \ 35 | .build-test-debug/debug/OpenAttributeGraphPackageTests.xctest \ 36 | > coverage.txt 37 | - name: Building and running tests in release mode 38 | run: | 39 | swift test \ 40 | -c release \ 41 | --build-path .build-test-release 42 | - uses: codecov/codecov-action@v3 43 | with: 44 | token: ${{ secrets.CODECOV_TOKEN }} 45 | verbose: true 46 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Misc/assert.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // assert.cpp 3 | // OpenAttributeGraphCxx 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | char* error_message = nullptr; 12 | 13 | namespace OAG { 14 | void precondition_failure(const char *format, ...) { 15 | char* s = nullptr; 16 | va_list va; 17 | va_start(va, format); 18 | vasprintf(&s, format, va); 19 | va_end(va); 20 | if (s != nullptr) { 21 | #if OAG_TARGET_OS_DARWIN 22 | os_log_error(error_log(), "precondition failure: %s", s); 23 | #endif /* OAG_TARGET_OS_DARWIN */ 24 | #if OAG_TARGET_RELEASE >= OAG_RELEASE_2023 25 | // OAG::Graph::trace_assertion_failure(true, "precondition failure: %s", s) 26 | #endif 27 | if (error_message == nullptr) { 28 | asprintf(&error_message, "OpenAttributeGraph precondition failure: %s.\n", s); 29 | } 30 | free(s); 31 | } 32 | abort(); 33 | } 34 | 35 | void non_fatal_precondition_failure(const char *format, ...) { 36 | char* s = nullptr; 37 | va_list va; 38 | va_start(va, format); 39 | vasprintf(&s, format, va); 40 | va_end(va); 41 | if (s != nullptr) { 42 | #if OAG_TARGET_OS_DARWIN 43 | os_log_fault(error_log(), "precondition failure: %s", s); 44 | #endif /* OAG_TARGET_OS_DARWIN */ 45 | free(s); 46 | } 47 | return; 48 | } 49 | } /* OAG */ 50 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/module.private.modulemap: -------------------------------------------------------------------------------- 1 | module OpenAttributeGraphCxx_Private { 2 | export * 3 | } 4 | 5 | module OpenAttributeGraphCxx_Private.Attribute { 6 | requires cplusplus 7 | umbrella "OpenAttributeGraphCxx/Attribute" 8 | export * 9 | } 10 | 11 | module OpenAttributeGraphCxx_Private.Comparison { 12 | requires cplusplus 13 | umbrella "OpenAttributeGraphCxx/Comparison" 14 | export * 15 | } 16 | 17 | module OpenAttributeGraphCxx_Private.Data { 18 | requires cplusplus 19 | umbrella "OpenAttributeGraphCxx/Data" 20 | export * 21 | } 22 | 23 | module OpenAttributeGraphCxx_Private.DebugServer { 24 | requires cplusplus 25 | umbrella "OpenAttributeGraphCxx/DebugServer" 26 | export * 27 | } 28 | 29 | module OpenAttributeGraphCxx_Private.Graph { 30 | requires cplusplus 31 | umbrella "OpenAttributeGraphCxx/Graph" 32 | export * 33 | } 34 | 35 | module OpenAttributeGraphCxx_Private.Misc { 36 | requires cplusplus 37 | umbrella "OpenAttributeGraphCxx/Misc" 38 | export * 39 | } 40 | 41 | module OpenAttributeGraphCxx_Private.Runtime { 42 | requires cplusplus 43 | umbrella "OpenAttributeGraphCxx/Runtime" 44 | export * 45 | } 46 | 47 | module OpenAttributeGraphCxx_Private.Util { 48 | requires cplusplus 49 | umbrella "OpenAttributeGraphCxx/Util" 50 | export * 51 | module * { export * } 52 | } 53 | 54 | module OpenAttributeGraphCxx_Private.Vector { 55 | requires cplusplus 56 | umbrella "OpenAttributeGraphCxx/Vector" 57 | export * 58 | } 59 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Attribute/Weak/AnyWeakAttribute.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnyWeakAttribute.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for 6.5.1 6 | // Status: Complete 7 | 8 | public import OpenAttributeGraphCxx 9 | 10 | extension AnyWeakAttribute { 11 | public init(_ attribute: AnyAttribute?) { 12 | self = __OAGCreateWeakAttribute(attribute ?? .nil) 13 | } 14 | 15 | public init(_ weakAttribute: WeakAttribute) { 16 | self = weakAttribute.base 17 | } 18 | 19 | public func unsafeCast(to _: Value.Type) -> WeakAttribute { 20 | WeakAttribute(base: self) 21 | } 22 | 23 | public var attribute: AnyAttribute? { 24 | get { 25 | let attribute = __OAGWeakAttributeGetAttribute(self) 26 | return attribute == .nil ? nil : attribute 27 | } 28 | set { 29 | self = AnyWeakAttribute(newValue) 30 | } 31 | } 32 | } 33 | 34 | extension AnyWeakAttribute: Swift.Hashable { 35 | public static func == (lhs: AnyWeakAttribute, rhs: AnyWeakAttribute) -> Bool { 36 | lhs._details.identifier == rhs._details.identifier && lhs._details.seed == rhs._details.seed 37 | } 38 | 39 | public func hash(into hasher: inout Hasher) { 40 | hasher.combine(_details.identifier) 41 | hasher.combine(_details.seed) 42 | } 43 | } 44 | 45 | extension AnyWeakAttribute: Swift.CustomStringConvertible { 46 | @_alwaysEmitIntoClient 47 | public var description: String { attribute?.description ?? "nil" } 48 | } 49 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/Attribute/Optional/OptionalAttributeCompatibilityTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OptionalAttributeCompatibilityTests.swift 3 | // OpenAttributeGraphCompatibilityTests 4 | 5 | import Testing 6 | 7 | #if canImport(Darwin) 8 | @MainActor 9 | @Suite(.disabled(if: !compatibilityTestEnabled, "OptionalAttribute is not implemented")) 10 | struct OptionalAttributeCompatibilityTests { 11 | @Test 12 | func basicInit() { 13 | let ao1 = AnyOptionalAttribute() 14 | let o1 = OptionalAttribute() 15 | #expect(o1 == OptionalAttribute(base: ao1)) 16 | 17 | let attr = Attribute(identifier: .init(rawValue: 0x1)) 18 | let ao2 = AnyOptionalAttribute(attr.identifier) 19 | let o2 = OptionalAttribute(attr) 20 | #expect(o2 == OptionalAttribute(base: ao2)) 21 | 22 | let o3 = OptionalAttribute(nil) 23 | #expect(o3.base.identifier == .nil) 24 | } 25 | 26 | @Test(.disabled("crash for invalid data offset")) 27 | func initWithWeak() { 28 | let attr = Attribute(value: 0) 29 | let weakAttr = WeakAttribute(attr) 30 | let _ = OptionalAttribute(weakAttr) 31 | } 32 | 33 | @Test 34 | func description() { 35 | let o1 = OptionalAttribute() 36 | #expect(o1.description == "nil") 37 | 38 | let attr = AnyAttribute(rawValue: 0x1) 39 | let o2 = OptionalAttribute(Attribute(identifier: attr)) 40 | #expect(o2.description == "#1") 41 | } 42 | } 43 | #endif 44 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGAttributeType.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGAttributeType.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGAttributeType_h 6 | #define OAGAttributeType_h 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | OAG_ASSUME_NONNULL_BEGIN 14 | 15 | typedef struct OAGAttributeType OAGAttributeType; 16 | 17 | typedef struct OAG_SWIFT_NAME(_AttributeVTable) OAGAttributeVTable { 18 | unsigned long version; 19 | void (*_Nullable type_destroy)(OAGAttributeType *); 20 | void (*_Nullable self_destroy)(const OAGAttributeType *, void *); 21 | CFStringRef _Nullable (*_Nullable self_description)(const OAGAttributeType *, const void *); 22 | CFStringRef _Nullable (*_Nullable value_description)(const OAGAttributeType *, const void *); 23 | void (*_Nullable update_default)(const OAGAttributeType *, void *); 24 | } OAGAttributeVTable; 25 | 26 | typedef struct OAG_SWIFT_NAME(_AttributeType) OAGAttributeType { 27 | OAGTypeID self_id; 28 | OAGTypeID value_id; 29 | OAGClosureStorage update; 30 | const OAGAttributeVTable *vtable; 31 | OAGAttributeTypeFlags flags; 32 | 33 | uint32_t internal_offset; 34 | const unsigned char *_Nullable value_layout; 35 | 36 | struct { 37 | OAGTypeID type_id; 38 | const void *witness_table; 39 | } body_conformance; 40 | } OAGAttributeType; 41 | 42 | OAG_ASSUME_NONNULL_END 43 | 44 | #endif /* OAGAttributeType_h */ 45 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/Attribute/Weak/AnyWeakAttributeCompatibilityTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnyWeakAttributeCompatibilityTests.swift 3 | // OpenAttributeGraphCompatibilityTests 4 | 5 | import Testing 6 | 7 | #if canImport(Darwin) 8 | @MainActor 9 | @Suite(.enabled(if: compatibilityTestEnabled), .graphScope) 10 | struct AnyWeakAttributeCompatibilityTests { 11 | @Test 12 | func basic() { 13 | let w1 = AnyWeakAttribute(nil) 14 | let w2 = AnyWeakAttribute(WeakAttribute(nil)) 15 | #expect(w1.attribute == nil) 16 | #expect(w2.attribute == nil) 17 | #expect(w2.unsafeCast(to: Void.self) == WeakAttribute(base: w2)) 18 | } 19 | 20 | @Test 21 | func hashable() { 22 | let w1 = AnyWeakAttribute(nil) 23 | let w2 = AnyWeakAttribute(WeakAttribute(nil)) 24 | #expect(w1 == w2) 25 | _ = w1.hashValue 26 | } 27 | 28 | @Test 29 | func description() { 30 | let attr = Attribute(value: 1) 31 | if compatibilityTestEnabled { 32 | #expect(AnyWeakAttribute(attr.identifier).description != "nil") 33 | } 34 | #expect(AnyWeakAttribute(nil).description == "nil") 35 | } 36 | 37 | @Test 38 | func dict() { 39 | let w1 = AnyWeakAttribute(nil) 40 | let w2 = AnyWeakAttribute(Attribute(value: 0).identifier) 41 | let dict: [AnyWeakAttribute: Int] = [ 42 | w1: 1, 43 | w2: 2, 44 | ] 45 | #expect(dict[w1] == 1) 46 | #expect(dict[w2] == 2) 47 | } 48 | } 49 | #endif 50 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/Type-Introspection.md: -------------------------------------------------------------------------------- 1 | # Type Introspection 2 | 3 | Runtime type information and introspection utilities. 4 | 5 | ## Overview 6 | 7 | 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. 8 | 9 | TupleType provides specialized support for working with tuple types at runtime, enabling dynamic element access and memory management for heterogeneous data structures. 10 | 11 | ## Topics 12 | 13 | ### Type Metadata 14 | 15 | - ``Metadata`` 16 | - ``TupleType`` 17 | 18 | ### Metadata Creation 19 | 20 | - ``Metadata/init(_:)`` 21 | - ``TupleType/init(_:)`` 22 | - ``TupleType/init(_:)-9jmk1`` 23 | - ``TupleType/init(count:elements:)`` 24 | 25 | ### Type Properties 26 | 27 | - ``Metadata/description`` 28 | - ``TupleType/type`` 29 | - ``TupleType/count`` 30 | - ``TupleType/size`` 31 | 32 | ### Tuple Operations 33 | 34 | - ``UnsafeTuple`` 35 | - ``UnsafeMutableTuple`` 36 | - ``withUnsafeTuple(of:count:_:)`` 37 | 38 | ### Runtime Utilities 39 | 40 | - ``MemoryLayout/offset(of:)`` 41 | - ``PointerOffset`` 42 | 43 | ### Memory Layout 44 | 45 | - ``PointerOffset/offset(_:)`` 46 | - ``PointerOffset/byteOffset`` 47 | - ``Attribute/unsafeOffset(at:as:)`` 48 | - ``Attribute/applying(offset:)`` 49 | - ``TupleType/elementOffset(at:type:)`` 50 | 51 | ### Type Validation 52 | 53 | - ``Attribute/validate()`` 54 | - ``AnyAttribute/verify(type:)`` 55 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph/Dependency-Graphs.md: -------------------------------------------------------------------------------- 1 | # Dependency Graphs 2 | 3 | Graph structures that manage attribute dependencies and updates. 4 | 5 | ## Overview 6 | 7 | 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. 8 | 9 | Graphs automatically track dependencies as attributes access other attributes during computation, building an efficient dependency network that minimizes unnecessary recalculations when changes occur. 10 | 11 | ## Topics 12 | 13 | ### Graph Types 14 | 15 | - ``Graph`` 16 | - ``Subgraph`` 17 | 18 | ### Graph Creation 19 | 20 | - ``Graph/init()`` 21 | - ``Subgraph/init()`` 22 | 23 | ### Graph Management 24 | 25 | - ``Graph/typeIndex(ctx:body:valueType:flags:update:)`` 26 | - ``Subgraph/currentGraphContext`` 27 | 28 | ### Update Coordination 29 | 30 | - ``Graph/willInvalidate(attribute:)`` 31 | - ``Graph/updateValue()`` 32 | - ``Subgraph/update()`` 33 | 34 | ### Graph Traversal 35 | 36 | - ``Attribute/breadthFirstSearch(options:_:)`` 37 | - ``AnyAttribute/breadthFirstSearch(options:_:)`` 38 | 39 | ### Input Management 40 | 41 | - ``Attribute/addInput(_:options:token:)`` 42 | - ``Attribute/addInput(_:options:token:)-6p8bn`` 43 | - ``AnyAttribute/addInput(_:options:token:)`` 44 | 45 | ### Graph Properties 46 | 47 | - ``Attribute/graph`` 48 | - ``Attribute/subgraph`` 49 | - ``AnyAttribute/graph`` 50 | - ``AnyAttribute/subgraph`` -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OpenAttributeGraph-umbrella.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | OAG_EXPORT double OpenAttributeGraphVersionNumber; 32 | OAG_EXPORT const unsigned char OpenAttributeGraphVersionString[]; 33 | -------------------------------------------------------------------------------- /CREDITS.md: -------------------------------------------------------------------------------- 1 | # Credits 2 | 3 | This project uses third-party libraries and code. Their licenses and acknowledgements are listed below. 4 | 5 | --- 6 | 7 | ## Compute 8 | 9 | OpenAttributeGraphCxx's Data, Graph, Vector and more is modified based on [Compute](https://github.com/jcmosc/Compute)'s implementations. 10 | 11 | Compute is licensed as follows: 12 | 13 | ``` 14 | MIT License 15 | 16 | Copyright (c) 2025 James Moschou 17 | 18 | Permission is hereby granted, free of charge, to any person obtaining a copy 19 | of this software and associated documentation files (the "Software"), to deal 20 | in the Software without restriction, including without limitation the rights 21 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | copies of the Software, and to permit persons to whom the Software is 23 | furnished to do so, subject to the following conditions: 24 | 25 | The above copyright notice and this permission notice shall be included in all 26 | copies or substantial portions of the Software. 27 | 28 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 31 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 33 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 34 | SOFTWARE. 35 | ``` 36 | 37 | --- 38 | 39 | ## Apple Open Source 40 | 41 | Part of the header file is from Apple Open Source project which is licensed under APSL. 42 | 43 | --- 44 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Graph/Subgraph.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Subgraph.cpp 3 | // OpenAttributeGraphCxx 4 | 5 | #include 6 | #include 7 | 8 | pthread_key_t OAG::Subgraph::_current_subgraph_key; 9 | 10 | OAG::Subgraph* OAG::Subgraph::from_cf(OAGSubgraphRef storage) OAG_NOEXCEPT { 11 | return storage->subgraph; 12 | } 13 | 14 | void OAG::Subgraph::clear_object() const OAG_NOEXCEPT { 15 | // TODO 16 | } 17 | 18 | void OAG::Subgraph::invalidate_and_delete_(bool) const OAG_NOEXCEPT { 19 | // TODO 20 | } 21 | 22 | void OAG::Subgraph::apply(OAGAttributeFlags flags, OAG::ClosureFunction body) const OAG_NOEXCEPT { 23 | // TODO 24 | } 25 | 26 | OAG::Subgraph::Subgraph(OAG::SubgraphObject* cf_subgraph, OAG::Graph::Context& context, OAG::AttributeID): 27 | _cf_subgraph((OAGSubgraphRef)cf_subgraph), // FIXME 28 | _context((OAGGraphContextStorage &)context){ 29 | // TODO 30 | } 31 | 32 | OAGUniqueID OAG::Subgraph::add_observer(OAG::ClosureFunction observer) const OAG_NOEXCEPT { 33 | // TODO 34 | return OAGMakeUniqueID(); 35 | } 36 | 37 | void OAG::Subgraph::remove_observer(OAGUniqueID observerID) const OAG_NOEXCEPT { 38 | // TODO 39 | } 40 | 41 | void OAG::Subgraph::begin_tree(OAG::AttributeID id, OAG::swift::metadata const* type, unsigned int flags) const OAG_NOEXCEPT { 42 | // TODO 43 | } 44 | 45 | void OAG::Subgraph::add_tree_value(OAG::AttributeID id, OAG::swift::metadata const *type, const char* key, uint32_t flags) const OAG_NOEXCEPT { 46 | // TODO 47 | } 48 | 49 | void OAG::Subgraph::end_tree(OAG::AttributeID id) const OAG_NOEXCEPT { 50 | // TODO 51 | } 52 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Attribute/Optional/AnyOptionalAttribute.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnyOptionalAttribute.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: Complete 7 | 8 | @frozen 9 | public struct AnyOptionalAttribute { 10 | public var identifier: AnyAttribute 11 | 12 | public init() { 13 | identifier = .nil 14 | } 15 | 16 | public init(_ attribute: AnyAttribute) { 17 | identifier = attribute 18 | } 19 | 20 | public init(_ attribute: AnyAttribute?) { 21 | identifier = attribute ?? .nil 22 | } 23 | 24 | init(_ weakAttribute: AnyWeakAttribute) { 25 | identifier = __OAGWeakAttributeGetAttribute(weakAttribute) 26 | } 27 | 28 | public init(_ attribute: OptionalAttribute) { 29 | self = attribute.base 30 | } 31 | 32 | public static var current: AnyOptionalAttribute { 33 | AnyOptionalAttribute(__OAGGraphGetCurrentAttribute()) 34 | } 35 | 36 | public var attribute: AnyAttribute? { 37 | get { identifier == .nil ? nil : identifier } 38 | set { identifier = newValue ?? .nil } 39 | } 40 | 41 | public func map(_ body: (AnyAttribute) -> Value) -> Value? { 42 | if let attribute { body(attribute) } else { nil } 43 | } 44 | 45 | public func unsafeCast(to _: Value.Type) -> OptionalAttribute { 46 | OptionalAttribute(base: self) 47 | } 48 | } 49 | 50 | extension AnyOptionalAttribute: Hashable {} 51 | 52 | extension AnyOptionalAttribute: CustomStringConvertible { 53 | public var description: String { 54 | attribute?.description ?? "nil" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /.github/workflows/compatibility_tests.yml: -------------------------------------------------------------------------------- 1 | name: Compatibility tests 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | compatibility_tests_macos: 11 | name: Execute compatibility tests 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | include: 16 | - os: macos-15 17 | xcode-version: "16.4" # Swift 6.1.2 18 | runs-on: ${{ matrix.os }} 19 | env: 20 | OPENATTRIBUTEGRAPH_WERROR: 1 21 | OPENATTRIBUTEGRAPH_ATTRIBUTEGRAPH: 1 22 | OPENATTRIBUTEGRAPH_COMPATIBILITY_TEST: 1 23 | OPENATTRIBUTEGRAPH_USE_LOCAL_DEPS: 1 24 | OPENATTRIBUTEGRAPH_TARGET_RELEASE: 2024 25 | DARWINPRIVATEFRAMEWORKS_TARGET_RELEASE: 2024 26 | GH_TOKEN: ${{ github.token }} 27 | steps: 28 | - uses: actions/checkout@v4 29 | - name: Setup Xcode 30 | uses: OpenSwiftUIProject/OpenSwiftUI/.github/actions/setup-xcode@main 31 | with: 32 | xcode-version: ${{ matrix.xcode-version }} 33 | - name: Set up build environment 34 | run: Scripts/CI/darwin_setup_build.sh 35 | shell: bash 36 | - name: Swift version 37 | run: swift --version 38 | - name: Run tests against Apple's AttributeGraph on macOS via SwiftPM 39 | run: | 40 | swift test \ 41 | --build-path .build-compatibility-test-debug 42 | - name: Run tests against Apple's AttributeGraph on macOS via Xcode 43 | run: | 44 | xcodebuild test \ 45 | -scheme OpenAttributeGraph-Package \ 46 | -sdk macosx \ 47 | -destination "platform=macOS" \ 48 | -skipPackagePluginValidation \ 49 | -skipMacroValidation -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Graph/Graph.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Graph.cpp 3 | // OpenAttributeGraphCxx 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #if !OAG_TARGET_OS_WASI 10 | #include 11 | #endif 12 | 13 | #include 14 | 15 | pthread_key_t OAG::Graph::_current_update_key; 16 | 17 | OAG::Graph::Graph() OAG_NOEXCEPT { 18 | // TODO 19 | 20 | // libdispatch is not supported on WASI 21 | // Tracked via https://github.com/swiftwasm/swift/issues/5565 22 | #if !OAG_TARGET_OS_WASI 23 | static dispatch_once_t make_keys; 24 | dispatch_once_f(&make_keys, nullptr, [](void * _Nullable context){ 25 | pthread_key_create(&_current_update_key, nullptr); 26 | OAG::Subgraph::make_current_subgraph_key(); 27 | }); 28 | #endif 29 | 30 | // TODO 31 | } 32 | 33 | const void OAG::Graph::value_mark_all() const OAG_NOEXCEPT { 34 | // TODO 35 | } 36 | 37 | void OAG::Graph::all_start_profiling(uint32_t) OAG_NOEXCEPT { 38 | // TODO 39 | } 40 | void OAG::Graph::all_stop_profiling() OAG_NOEXCEPT { 41 | // TODO 42 | } 43 | void OAG::Graph::start_profiling(uint32_t) OAG_NOEXCEPT { 44 | // TODO 45 | } 46 | void OAG::Graph::stop_profiling() OAG_NOEXCEPT { 47 | // TODO 48 | } 49 | 50 | const bool OAG::Graph::thread_is_updating() const OAG_NOEXCEPT { 51 | void *current = pthread_getspecific(current_key()); 52 | if (!current) { 53 | return false; 54 | } 55 | // TODO 56 | return false; 57 | } 58 | 59 | const bool OAG::Graph::is_context_updating(const OAG::Graph::Context&) const OAG_NOEXCEPT { 60 | // TODO 61 | return false; 62 | } 63 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphShimsTests/Attribute+DebugTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Attribute+DebugTests.swift 3 | // OpenAttributeGraphShimsTests 4 | 5 | #if canImport(Darwin) && DEBUG 6 | 7 | import Testing 8 | import OpenAttributeGraphShims 9 | 10 | @MainActor 11 | @Suite(.disabled(if: !attributeGraphEnabled, "Subgraph is not implemented on OAG"), .graphScope) 12 | struct Attribute_DebugTests { 13 | @Test 14 | func directAttribute() { 15 | let attribute = Attribute(value: 3) 16 | 17 | #expect(attribute.debugDescription == #""" 18 | Attribute { 19 | rawValue: \#(attribute.identifier.rawValue) 20 | graph: \#(attribute.graph) 21 | (direct attribute) 22 | valueType: Int 23 | value: 3 24 | bodyType: External 25 | bodyValue: 26 | Int 27 | } 28 | """#) 29 | } 30 | 31 | @Test 32 | func indirectAttribute() { 33 | let tuple = Attribute(value: Tuple(first: 1, second: "2")) 34 | let second = tuple[keyPath: \.second] 35 | #expect(second.debugDescription == #""" 36 | Attribute { 37 | rawValue: \#(second.identifier.rawValue) 38 | graph: \#(second.graph) 39 | (indirect attribute) 40 | source attribute: 41 | rawValue: \#(tuple.identifier.rawValue) 42 | graph: \#(tuple.graph) 43 | (direct attribute) 44 | valueType: Tuple 45 | value: Tuple(first: 1, second: "2") 46 | bodyType: External> 47 | bodyValue: 48 | Tuple 49 | } 50 | """#) 51 | } 52 | } 53 | #endif 54 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/RuleContext/RuleContext.md: -------------------------------------------------------------------------------- 1 | # ``RuleContext`` 2 | 3 | Context object providing access to rule evaluation state and input values. 4 | 5 | ## Overview 6 | 7 | `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. 8 | 9 | The context ensures that dependency tracking is properly maintained while providing convenient access to input attributes. 10 | 11 | ## Key Features 12 | 13 | - Type-safe input access: Access dependent attribute values with full type safety 14 | - Dependency tracking: Automatically tracks accessed attributes as dependencies 15 | - Value management: Direct access to current and changed values 16 | - Context isolation: Maintains evaluation context for proper dependency resolution 17 | 18 | ## Usage in Rules 19 | 20 | RuleContext is typically used within ``StatefulRule`` implementations to access dependencies and manage the rule's output value: 21 | 22 | struct MyRule: StatefulRule { 23 | let inputAttribute: Attribute 24 | 25 | mutating func updateValue() { 26 | let inputValue = context[inputAttribute] 27 | value = inputValue * 2 28 | } 29 | } 30 | 31 | ## Topics 32 | 33 | ### Creating Context 34 | 35 | - ``init(attribute:)`` 36 | 37 | ### Input Access 38 | 39 | - ``subscript(_:)-1g3wa`` 40 | - ``subscript(_:)-6y4wa`` 41 | - ``subscript(_:)-2h8nh`` 42 | 43 | ### Value Management 44 | 45 | - ``value`` 46 | - ``hasValue`` 47 | 48 | ### Change Tracking 49 | 50 | - ``changedValueFlagged(options:)`` 51 | - ``wasModified(options:)`` 52 | 53 | ### Associated Attribute 54 | 55 | - ``attribute`` -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Attribute/Optional/OptionalAttribute.md: -------------------------------------------------------------------------------- 1 | # ``OptionalAttribute`` 2 | 3 | An optional attribute wrapper that may or may not contain a value. 4 | 5 | ## Overview 6 | 7 | `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. 8 | 9 | @OptionalAttribute var maybeAttribute: Int? 10 | 11 | if let value = maybeAttribute { 12 | print("Attribute value: \(value)") 13 | } 14 | 15 | The optional attribute wrapper automatically handles the optional nature of attribute references while maintaining the reactive capabilities of the attribute system. 16 | 17 | ## Key Features 18 | 19 | - Optional semantics: Natural handling of attributes that may not exist 20 | - Conditional access: Safe access to potentially nil attributes 21 | - Reactive updates: Changes propagate when the attribute becomes available 22 | - Integration with weak attributes: Works seamlessly with ``WeakAttribute`` 23 | 24 | ## Usage Pattern 25 | 26 | OptionalAttribute is commonly used for: 27 | - Conditionally created UI elements 28 | - Optional data model properties 29 | - Weak attribute references that may become nil 30 | - Lazy initialization scenarios 31 | 32 | ## Topics 33 | 34 | ### Creating Optional Attributes 35 | 36 | - ``init()`` 37 | - ``init(base:)`` 38 | - ``init(_:)-47ane`` 39 | - ``init(_:)-9eqjv`` 40 | - ``init(_:)-2u3gq`` 41 | 42 | ### Property Wrapper 43 | 44 | - ``wrappedValue`` 45 | - ``projectedValue`` 46 | 47 | ### Value Access 48 | 49 | - ``attribute`` 50 | - ``value`` 51 | - ``changedValue(options:)`` 52 | 53 | ### Transformations 54 | 55 | - ``map(_:)`` 56 | 57 | ### Base Access 58 | 59 | - ``base`` -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/UnsafeMutableTuple.md: -------------------------------------------------------------------------------- 1 | # ``UnsafeMutableTuple`` 2 | 3 | Mutable tuple buffer for dynamic tuple creation, modification, and memory management. 4 | 5 | ## Overview 6 | 7 | `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. 8 | 9 | let mutableTuple = UnsafeMutableTuple(with: tupleType) 10 | 11 | // Initialize elements 12 | mutableTuple.initialize(at: 0, to: 42) 13 | mutableTuple.initialize(at: 1, to: "Hello") 14 | 15 | // Access and modify 16 | mutableTuple[0] = 100 17 | let value: String = mutableTuple[1] 18 | 19 | // Clean up 20 | mutableTuple.deallocate(initialized: true) 21 | 22 | ## Key Features 23 | 24 | - Dynamic allocation: Create tuple buffers with proper memory alignment 25 | - Element initialization: Initialize tuple elements in-place with type safety 26 | - Mutation operations: Modify tuple elements after creation 27 | - Memory management: Proper cleanup with element-wise deinitialization 28 | - Lifecycle control: Manual control over initialization and deallocation phases 29 | 30 | ## Topics 31 | 32 | ### Creating Mutable Tuples 33 | 34 | - ``init(with:)`` 35 | 36 | ### Element Initialization 37 | 38 | - ``initialize(at:to:)`` 39 | 40 | ### Memory Management 41 | 42 | - ``deinitialize()`` 43 | - ``deinitialize(at:)`` 44 | - ``deallocate(initialized:)`` 45 | 46 | ### Tuple Properties 47 | 48 | - ``count`` 49 | - ``isEmpty`` 50 | - ``indices`` 51 | 52 | ### Element Access 53 | 54 | - ``subscript()`` 55 | - ``subscript(_:)`` 56 | 57 | ### Address Operations 58 | 59 | - ``address(as:)`` 60 | - ``address(of:as:)`` -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/Attribute/Optional/AnyOptionalAttributeCompatibilityTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnyOptionalAttributeCompatibilityTests.swift 3 | // OpenAttributeGraphCompatibilityTests 4 | 5 | import Testing 6 | 7 | #if canImport(Darwin) 8 | @MainActor 9 | @Suite(.disabled(if: !compatibilityTestEnabled, "AnyOptionalAttribute is not implemented"), .graphScope) 10 | struct AnyOptionalAttributeCompatibilityTests { 11 | @Test 12 | func basicInit() { 13 | let o1 = AnyOptionalAttribute() 14 | #expect(o1.identifier == .nil) 15 | 16 | let attr = AnyAttribute(rawValue: 0x1) 17 | let o2 = AnyOptionalAttribute(attr) 18 | #expect(o2.identifier == attr) 19 | 20 | let o3 = AnyOptionalAttribute(nil) 21 | #expect(o3.identifier == .nil) 22 | } 23 | 24 | @Test 25 | func attribute() { 26 | let o1 = AnyOptionalAttribute() 27 | #expect(o1.attribute == nil) 28 | 29 | let attr = AnyAttribute(rawValue: 0x1) 30 | let o2 = AnyOptionalAttribute(attr) 31 | #expect(o2.attribute != nil) 32 | } 33 | 34 | @Test 35 | func current() { 36 | let currentNil = AnyOptionalAttribute.current 37 | #expect(currentNil.identifier == .nil) 38 | } 39 | 40 | @Test 41 | func description() { 42 | let o1 = AnyOptionalAttribute() 43 | #expect(o1.description == "nil") 44 | 45 | let attr = AnyAttribute(rawValue: 0x1) 46 | let o2 = AnyOptionalAttribute(attr) 47 | #expect(o2.description == "#1") 48 | } 49 | 50 | @Test("Test symbol link") 51 | func other() { 52 | let optional = OptionalAttribute() 53 | let anyOptional = AnyOptionalAttribute(optional) 54 | _ = anyOptional.unsafeCast(to: Int.self) 55 | _ = anyOptional.map { _ in 0 } 56 | } 57 | } 58 | #endif 59 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Graph/Graph.md: -------------------------------------------------------------------------------- 1 | # ``Graph`` 2 | 3 | The central coordinator for attribute relationships and update cycles. 4 | 5 | ## Overview 6 | 7 | `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. 8 | 9 | The graph automatically tracks dependencies when attributes are accessed during rule evaluation, detects cycles, and batches updates for optimal performance. 10 | 11 | ## Key Features 12 | 13 | - Dependency tracking: Automatically discovers and maintains attribute relationships 14 | - Cycle detection: Prevents and detects circular dependencies 15 | - Batch updates: Groups multiple changes for efficient processing 16 | - Update scheduling: Coordinates when and how attributes are recomputed 17 | - Performance monitoring: Profiling and debugging capabilities 18 | 19 | ## Update Propagation 20 | 21 | When an attribute changes, the graph efficiently propagates updates through three phases: 22 | 1. Mark phase: Changed attributes are marked as invalid 23 | 2. Sweep phase: Dependent attributes are transitively marked 24 | 3. Update phase: Values are recomputed in dependency order 25 | 26 | ## Topics 27 | 28 | ### Update Control 29 | 30 | - ``withoutUpdate(_:)`` 31 | - ``withoutSubgraphInvalidation(_:)`` 32 | - ``withDeadline(_:_:)`` 33 | 34 | ### Callbacks 35 | 36 | - ``onInvalidation(_:)`` 37 | - ``onUpdate(_:)`` 38 | 39 | ### Performance Monitoring 40 | 41 | - ``startProfiling()`` 42 | - ``stopProfiling()`` 43 | - ``resetProfile()`` 44 | 45 | ### Statistics 46 | 47 | - ``mainUpdates`` 48 | 49 | ### Global Operations 50 | 51 | - ``anyInputsChanged(excluding:)`` 52 | 53 | ### Output Management 54 | 55 | - ``outputValue()`` 56 | - ``setOutputValue(_:)`` 57 | 58 | ### Archive and Debug 59 | 60 | - ``archiveJSON(name:)`` -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGGraphTracing.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGGraphTracing.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGGraphTracing_hpp 6 | #define OAGGraphTracing_hpp 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | typedef OAG_OPTIONS(uint32_t, OAGGraphTraceOptions) { 13 | OAGGraphTraceOptionsEnabled = 1 << 0, 14 | OAGGraphTraceOptionsFull = 1 << 1, 15 | OAGGraphTraceOptionsBacktrace = 1 << 2, 16 | OAGGraphTraceOptionsPrepare = 1 << 3, 17 | OAGGraphTraceOptionsCustom = 1 << 4, 18 | OAGGraphTraceOptionsAll = 1 << 5, 19 | } OAG_SWIFT_NAME(OAGGraphRef.TraceOptions); 20 | 21 | typedef struct OAGTrace *OAGTraceRef; 22 | 23 | OAG_ASSUME_NONNULL_BEGIN 24 | 25 | OAG_IMPLICIT_BRIDGING_ENABLED 26 | 27 | OAG_EXTERN_C_BEGIN 28 | 29 | OAG_EXPORT 30 | OAG_REFINED_FOR_SWIFT 31 | void OAGGraphStartTracing(_Nullable OAGGraphRef graph, OAGGraphTraceOptions options) OAG_SWIFT_NAME(OAGGraphRef.startTracing(_:options:)); 32 | 33 | OAG_EXPORT 34 | OAG_REFINED_FOR_SWIFT 35 | void OAGGraphStartTracing2(_Nullable OAGGraphRef graph, OAGGraphTraceOptions options, _Nullable CFArrayRef subsystems) OAG_SWIFT_NAME(OAGGraphRef.startTracing(_:flags:subsystems:)); 36 | 37 | OAG_EXPORT 38 | OAG_REFINED_FOR_SWIFT 39 | void OAGGraphStopTracing(_Nullable OAGGraphRef graph) OAG_SWIFT_NAME(OAGGraphRef.stopTracing(_:)); 40 | 41 | OAG_EXPORT 42 | OAG_REFINED_FOR_SWIFT 43 | OAGUniqueID OAGGraphAddTrace(OAGGraphRef graph, const OAGTraceRef trace, void *_Nullable context) 44 | OAG_SWIFT_NAME(OAGGraphRef.addTrace(self:_:context:)); 45 | 46 | OAG_EXPORT 47 | OAG_REFINED_FOR_SWIFT 48 | void OAGGraphRemoveTrace(OAGGraphRef graph, OAGUniqueID trace_id) OAG_SWIFT_NAME(OAGGraphRef.removeTrace(self:traceID:)); 49 | 50 | OAG_EXTERN_C_END 51 | 52 | OAG_IMPLICIT_BRIDGING_DISABLED 53 | 54 | OAG_ASSUME_NONNULL_END 55 | 56 | #endif /* OAGGraphTracing_hpp */ 57 | -------------------------------------------------------------------------------- /.github/workflows/macos.yml: -------------------------------------------------------------------------------- 1 | name: macOS 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | macos_test: 11 | name: Execute tests on macOS 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | os: [macos-15] 16 | xcode-version: ["16.4"] # Swift 6.1.2 17 | runs-on: ${{ matrix.os }} 18 | env: 19 | OPENATTRIBUTEGRAPH_WERROR: 1 20 | OPENATTRIBUTEGRAPH_ATTRIBUTEGRAPH: 0 21 | OPENATTRIBUTEGRAPH_COMPATIBILITY_TEST: 0 22 | OPENATTRIBUTEGRAPH_USE_LOCAL_DEPS: 1 23 | OPENATTRIBUTEGRAPH_TARGET_RELEASE: 2024 24 | DARWINPRIVATEFRAMEWORKS_TARGET_RELEASE: 2024 25 | GH_TOKEN: ${{ github.token }} 26 | steps: 27 | - uses: actions/checkout@v4 28 | - name: Setup Xcode 29 | uses: OpenSwiftUIProject/OpenSwiftUI/.github/actions/setup-xcode@main 30 | with: 31 | xcode-version: ${{ matrix.xcode-version }} 32 | - name: Set up build environment 33 | run: Scripts/CI/darwin_setup_build.sh 34 | shell: bash 35 | - name: Swift version 36 | run: swift --version 37 | - name: Build and run tests in debug mode with coverage 38 | run: | 39 | swift test \ 40 | -c debug \ 41 | --enable-code-coverage \ 42 | --build-path .build-test-debug 43 | xcrun llvm-cov show \ 44 | -instr-profile=.build-test-debug/debug/codecov/default.profdata \ 45 | .build-test-debug/debug/OpenAttributeGraphPackageTests.xctest/Contents/MacOS/OpenAttributeGraphPackageTests \ 46 | > coverage.txt 47 | - name: Build and run tests in release mode 48 | run: | 49 | swift test \ 50 | -c release \ 51 | --enable-code-coverage \ 52 | --build-path .build-test-release 53 | - uses: codecov/codecov-action@v5 54 | with: 55 | token: ${{ secrets.CODECOV_TOKEN }} 56 | verbose: true 57 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphShimsTests/MetadataDebugTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetadataDebugTests.swift 3 | // OpenAttributeGraphShimsTests 4 | 5 | @_spi(Debug) import OpenAttributeGraphShims 6 | import Testing 7 | 8 | #if canImport(UIKit) 9 | import UIKit 10 | private typealias PlatformView = UIView 11 | #elseif canImport(AppKit) 12 | import AppKit 13 | private typealias PlatformView = NSView 14 | #endif 15 | 16 | @Suite(.disabled(if: !attributeGraphEnabled, "forEachField is not implemented for OAG")) 17 | struct MetadataDebugTests { 18 | struct Demo1 { 19 | var a: Int = .zero 20 | var b: Double = .zero 21 | } 22 | 23 | class Demo2 { 24 | var a: Int = .zero 25 | var b: Double = .zero 26 | } 27 | 28 | @Test 29 | func layout() { 30 | #expect(Metadata(Demo1.self).layoutDescription == #""" 31 | struct Demo1 { 32 | \#tvar a: Int // offset = 0x0 33 | \#tvar b: Double // offset = 0x8 34 | } 35 | 36 | """#) 37 | 38 | #expect(Metadata(Demo2.self).layoutDescription == #""" 39 | class Demo2 { 40 | \#tvar a: Int // offset = 0x10 41 | \#tvar b: Double // offset = 0x18 42 | } 43 | 44 | """#) 45 | } 46 | 47 | #if canImport(UIKit) || canImport(AppKit) 48 | @Test 49 | func unknownFields() { 50 | class DemoView: PlatformView { 51 | var a: Int = .zero 52 | var b: Double = .zero 53 | } 54 | let layoutDescription = Metadata(DemoView.self).layoutDescription.split(separator: "\n").map(String.init) 55 | #expect(layoutDescription[0] == "class DemoView {") 56 | #expect(layoutDescription[1].contains("var a: Int // offset = ")) 57 | #expect(layoutDescription[2].contains("var b: Double // offset = ")) 58 | #expect(layoutDescription[3] == "}") 59 | } 60 | #endif 61 | } 62 | 63 | extension Int { 64 | fileprivate var hex: String { 65 | "0x\(String(format:"%X", self))" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/Debug/DebugServerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DebugServerTests.swift 3 | // OpenAttributeGraphCompatibilityTests 4 | 5 | #if canImport(Darwin) 6 | import CoreFoundation 7 | import Foundation 8 | import Testing 9 | 10 | @MainActor 11 | struct DebugServerTests { 12 | @Test 13 | func testMode0() { 14 | #expect(DebugServer.start(mode: []) == nil) 15 | #expect(DebugServer.copyURL() == nil) 16 | } 17 | 18 | // To make AG start debugServer, we need to pass internal_diagnostics check. 19 | // In debug mode, we can breakpoint on `_ZN2AG11DebugServer5startEj` and 20 | // executable `reg write w0 1` after `internal_diagnostics` call. 21 | // Or we can disable SIP on the target darwinOS and run `sudo sysctl kern.osvariant_status=xx` to workaround. 22 | // Or you can add `breakpoint set -n os_variant_has_internal_diagnostics -C "thread return 1"` 23 | // to your lldbinit or run it before AGDebugServerStart call. 24 | @Test(.disabled(if: compatibilityTestEnabled, "Skip on AG on CI due to internal_diagnostics check")) 25 | func testMode1() throws { 26 | let _ = try #require(DebugServer.start(mode: [.valid])) 27 | let url = try #require(DebugServer.copyURL()) as URL 28 | #expect(url.scheme == "graph") 29 | let host = try #require(url.host) 30 | #expect(host == "127.0.0.1") 31 | DebugServer.run(timeout: 1) 32 | DebugServer.stop() 33 | } 34 | 35 | @Test(.disabled(if: compatibilityTestEnabled, "Skip on AG on CI due to internal_diagnostics check")) 36 | func testMode3() throws { 37 | let _ = try #require(DebugServer.start(mode: [.valid, .networkInterface])) 38 | let url = try #require(DebugServer.copyURL()) as URL 39 | #expect(url.scheme == "graph") 40 | let host = try #require(url.host) 41 | #expect(host != "127.0.0.1") 42 | #expect(host.hasPrefix("192.168")) 43 | DebugServer.run(timeout: 1) 44 | DebugServer.stop() 45 | } 46 | } 47 | #endif 48 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Attribute/Indirect/IndirectAttribute.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IndirectAttribute.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: Complete 7 | 8 | @frozen 9 | @propertyWrapper 10 | @dynamicMemberLookup 11 | public struct IndirectAttribute { 12 | public let identifier: AnyAttribute 13 | 14 | public init(source: Attribute) { 15 | identifier = source.identifier.createIndirect(size: UInt64(MemoryLayout.size)) 16 | } 17 | 18 | public var source: Attribute { 19 | get { Attribute(identifier: identifier.source) } 20 | nonmutating set { identifier.source = newValue.identifier } 21 | } 22 | 23 | public var dependency: AnyAttribute? { 24 | get { 25 | let dependency = identifier._indirectDependency 26 | return dependency == .nil ? nil : dependency 27 | } 28 | nonmutating set { identifier._indirectDependency = newValue ?? .nil } 29 | } 30 | 31 | public var value: Value { 32 | get { Attribute(identifier: identifier).value } 33 | nonmutating set { Attribute(identifier: identifier).value = newValue } 34 | nonmutating _modify { yield &Attribute(identifier: identifier).value } 35 | } 36 | 37 | public func changedValue(options: OAGValueOptions = []) -> (value: Value, changed: Bool) { 38 | Attribute(identifier: identifier).changedValue(options: options) 39 | } 40 | 41 | public var wrappedValue: Value { 42 | get { value } 43 | nonmutating set { value = newValue } 44 | nonmutating _modify { yield &value } 45 | } 46 | 47 | public var projectedValue: Attribute { 48 | Attribute(identifier: identifier) 49 | } 50 | 51 | public subscript(dynamicMember keyPath: KeyPath) -> Attribute { 52 | Attribute(identifier: identifier)[dynamicMember: keyPath] 53 | } 54 | } 55 | 56 | extension IndirectAttribute: Hashable {} 57 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Util/Heap.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Heap.hpp 3 | // OpenAttributeGraphCxx 4 | // 5 | // Status: Complete 6 | // Modified based Compute code 7 | 8 | #ifndef OPENATTRIBUTEGRAPH_CXX_UTIL_HEAP_HPP 9 | #define OPENATTRIBUTEGRAPH_CXX_UTIL_HEAP_HPP 10 | 11 | #include 12 | #include 13 | 14 | OAG_ASSUME_NONNULL_BEGIN 15 | 16 | namespace util { 17 | 18 | class Heap { 19 | protected: 20 | typedef struct Node { 21 | struct Node *next; 22 | void *buffer; 23 | } Node; 24 | 25 | size_t _increment; 26 | Node *_node; 27 | char *_free_start; 28 | size_t _capacity; 29 | 30 | void *alloc_(size_t arg1); 31 | 32 | public: 33 | static constexpr size_t minimum_increment = 0x400; 34 | 35 | static Heap *create(char *_Nullable start, size_t capacity, size_t increment); 36 | static void destroy(Heap *value); 37 | 38 | Heap(char *_Nullable start, size_t capacity, size_t increment); 39 | ~Heap(); 40 | 41 | // non-copyable 42 | Heap(const Heap &) = delete; 43 | Heap &operator=(const Heap &) = delete; 44 | 45 | // non-movable 46 | Heap(Heap &&) = delete; 47 | Heap &operator=(Heap &&) = delete; 48 | 49 | template inline T *_Nonnull alloc(size_t count = 1) { 50 | return static_cast(alloc_(sizeof(T) * count)); 51 | }; 52 | void reset(char *_Nullable start, size_t capacity); 53 | 54 | // Debugging 55 | 56 | size_t num_nodes() const; 57 | size_t increment() const { return _increment; } 58 | size_t capacity() const { return _capacity; } 59 | 60 | void print() const; 61 | } SWIFT_UNSAFE_REFERENCE; 62 | 63 | template class InlineHeap : public Heap { 64 | private: 65 | char _inline_buffer[_inline_size] = {}; 66 | 67 | public: 68 | InlineHeap() : Heap(_inline_buffer, _inline_size, 0) {} 69 | }; 70 | 71 | } /* namespace util */ 72 | 73 | OAG_ASSUME_NONNULL_END 74 | 75 | #endif /* OPENATTRIBUTEGRAPH_CXX_UTIL_HEAP_HPP */ 76 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGGraphDescription.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGGraphDescription.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGGraphDescription_h 6 | #define OAGGraphDescription_h 7 | 8 | #include 9 | #include 10 | 11 | OAG_ASSUME_NONNULL_BEGIN 12 | 13 | OAG_IMPLICIT_BRIDGING_ENABLED 14 | 15 | OAG_EXTERN_C_BEGIN 16 | 17 | #if OAG_OBJC_FOUNDATION 18 | 19 | typedef CFStringRef OAGDescriptionOption OAG_SWIFT_STRUCT OAG_SWIFT_NAME(DescriptionOption); 20 | 21 | OAG_EXPORT 22 | const OAGDescriptionOption OAGDescriptionFormat OAG_SWIFT_NAME(DescriptionOption.format); 23 | 24 | OAG_EXPORT 25 | const OAGDescriptionOption OAGDescriptionIncludeValues OAG_SWIFT_NAME(DescriptionOption.includeValues); 26 | 27 | OAG_EXPORT 28 | const OAGDescriptionOption OAGDescriptionTruncationLimit OAG_SWIFT_NAME(DescriptionOption.truncationLimit); 29 | 30 | OAG_EXPORT 31 | const OAGDescriptionOption OAGDescriptionMaxFrames OAG_SWIFT_NAME(DescriptionOption.maxFrames); 32 | 33 | static const CFStringRef OAGDescriptionFormatDot OAG_SWIFT_NAME(OAGGraphRef.descriptionFormatDot) = CFSTR("graph/dot"); 34 | 35 | static const CFStringRef OAGDescriptionFormatDictionary OAG_SWIFT_NAME(OAGGraphRef.descriptionFormatDictionary) = CFSTR("graph/dict"); 36 | 37 | static const CFStringRef OAGDescriptionAllGraphs OAG_SWIFT_NAME(OAGGraphRef.descriptionAllGraphs) = CFSTR("all_graphs"); 38 | 39 | #endif 40 | 41 | OAG_EXPORT 42 | OAG_REFINED_FOR_SWIFT 43 | void OAGGraphArchiveJSON(char const * _Nullable name) OAG_SWIFT_NAME(OAGGraphRef.archiveJSON(name:)); 44 | 45 | OAG_EXPORT 46 | OAG_REFINED_FOR_SWIFT 47 | void OAGGraphArchiveJSON2(char const * _Nullable name, bool exclude_values) OAG_SWIFT_NAME(OAGGraphRef.archiveJSON(name:excludeValues:)); 48 | 49 | OAG_EXPORT 50 | OAG_REFINED_FOR_SWIFT 51 | _Nullable CFTypeRef OAGGraphDescription(_Nullable OAGGraphRef graph, CFDictionaryRef options) OAG_SWIFT_NAME(OAGGraphRef.description(_:options:)); 52 | 53 | OAG_EXTERN_C_END 54 | 55 | OAG_IMPLICIT_BRIDGING_DISABLED 56 | 57 | OAG_ASSUME_NONNULL_END 58 | 59 | #endif /* OAGGraphDescription_h */ 60 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Attribute/Rule/Focus.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Focus.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: Complete 7 | 8 | /// A rule that focuses on a specific property of another attribute using KeyPath. 9 | /// 10 | /// `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. 11 | /// 12 | /// struct Person { 13 | /// let name: String 14 | /// let age: Int 15 | /// } 16 | /// 17 | /// @Attribute var person = Person(name: "Alice", age: 30) 18 | /// let nameAttribute = Attribute(Focus(root: $person, keyPath: \.name)) 19 | /// // nameAttribute automatically updates when person.name changes 20 | /// 21 | /// Focus is commonly used internally by OpenAttributeGraph's dynamic member lookup system to create property-specific attributes. 22 | /// 23 | /// ## Key Features 24 | /// 25 | /// - KeyPath-based focusing: Use any Swift KeyPath to focus on specific properties 26 | /// - Automatic updates: Changes to the focused property automatically propagate 27 | /// - Type safety: Full compile-time type checking for focused properties 28 | /// - Efficient tracking: Only tracks changes to the specific focused property 29 | /// 30 | /// ## Usage Pattern 31 | /// 32 | /// Focus is ideal for: 33 | /// - Creating focused views of complex data structures 34 | /// - Implementing dynamic member lookup for attributes 35 | /// - Breaking down large objects into smaller, more manageable attribute pieces 36 | /// - Selective observation of specific properties 37 | @frozen 38 | public struct Focus: Rule, CustomStringConvertible { 39 | public var root: Attribute 40 | public var keyPath: KeyPath 41 | 42 | public init(root: Attribute, keyPath: KeyPath) { 43 | self.root = root 44 | self.keyPath = keyPath 45 | } 46 | 47 | public var value: Value { root.value[keyPath: keyPath] } 48 | 49 | public static var flags: Flags { [] } 50 | 51 | public var description: String { "• \(Metadata(Value.self).description)" } 52 | } 53 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Attribute/Optional/OptionalAttribute.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OptionalAttribute.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: Complete 7 | 8 | /// An optional attribute wrapper that may or may not contain a value. 9 | @frozen 10 | @propertyWrapper 11 | @dynamicMemberLookup 12 | public struct OptionalAttribute { 13 | public var base: AnyOptionalAttribute 14 | 15 | public init() { 16 | base = AnyOptionalAttribute() 17 | } 18 | 19 | public init(base: AnyOptionalAttribute) { 20 | self.base = base 21 | } 22 | 23 | public init(_ attribute: Attribute) { 24 | base = AnyOptionalAttribute(attribute.identifier) 25 | } 26 | 27 | public init(_ attribute: Attribute?) { 28 | base = AnyOptionalAttribute(attribute?.identifier) 29 | } 30 | 31 | public init(_ weakAttribute: WeakAttribute) { 32 | base = AnyOptionalAttribute(weakAttribute.base) 33 | } 34 | 35 | public var attribute: Attribute? { 36 | get { base.attribute?.unsafeCast(to: Value.self) } 37 | set { base.attribute = newValue?.identifier } 38 | } 39 | 40 | public var value: Value? { attribute?.value } 41 | 42 | public func changedValue(options: OAGValueOptions = []) -> (value: Value, changed: Bool)? { 43 | attribute?.changedValue(options: options) 44 | } 45 | 46 | public func map(_ body: (Attribute) -> V) -> V? { 47 | if let attribute { body(attribute) } else { nil } 48 | } 49 | 50 | public var wrappedValue: Value? { value } 51 | 52 | public var projectedValue: Attribute? { 53 | get { attribute } 54 | set { attribute = newValue } 55 | _modify { yield &attribute } 56 | } 57 | 58 | public subscript(dynamicMember keyPath: KeyPath) -> Attribute? { 59 | attribute?[keyPath: keyPath] 60 | } 61 | } 62 | 63 | extension OptionalAttribute: Hashable {} 64 | 65 | extension OptionalAttribute: CustomStringConvertible { 66 | public var description: String { attribute?.description ?? "nil" } 67 | } 68 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Data/ClosureFunction.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // ClosureFunction.hpp 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef ClosureFunction_hpp 6 | #define ClosureFunction_hpp 7 | 8 | #include 9 | #include 10 | 11 | OAG_ASSUME_NONNULL_BEGIN 12 | 13 | namespace OAG { 14 | template 15 | class ClosureFunction final { 16 | public: 17 | typedef const void * _Nullable Context; 18 | typedef const ReturnType (* _Nullable Callable)(Context OAG_SWIFT_CONTEXT, Args...) OAG_SWIFT_CC(swift); 19 | 20 | OAG_INLINE OAG_CONSTEXPR 21 | ClosureFunction(Callable function, Context context) OAG_NOEXCEPT : 22 | _function(function), 23 | _context(context) { 24 | } 25 | 26 | OAG_INLINE OAG_CONSTEXPR 27 | ClosureFunction(std::nullptr_t) OAG_NOEXCEPT : 28 | _function(nullptr), 29 | _context(nullptr) { 30 | } 31 | 32 | OAG_INLINE 33 | ~ClosureFunction() noexcept { 34 | } 35 | 36 | OAG_INLINE OAG_CONSTEXPR 37 | ClosureFunction(const ClosureFunction &value) OAG_NOEXCEPT : 38 | _function(value._function), 39 | _context(value._context) { 40 | } 41 | 42 | OAG_INLINE OAG_CONSTEXPR 43 | explicit operator bool() const OAG_NOEXCEPT { 44 | return _function != nullptr; 45 | } 46 | 47 | OAG_INLINE OAG_CONSTEXPR 48 | bool operator==(const ClosureFunction &rhs) const OAG_NOEXCEPT { 49 | return _function == rhs._function && _context == rhs._context; 50 | } 51 | 52 | OAG_INLINE OAG_CONSTEXPR 53 | bool operator==(std::nullptr_t) const OAG_NOEXCEPT { 54 | return _function == nullptr; 55 | } 56 | 57 | OAG_INLINE OAG_CONSTEXPR 58 | bool operator!=(std::nullptr_t) const OAG_NOEXCEPT { 59 | return _function != nullptr; 60 | } 61 | 62 | OAG_INLINE OAG_CONSTEXPR 63 | const ReturnType operator()(Args... args) const OAG_NOEXCEPT { 64 | return _function(_context, std::forward(args)...); 65 | } 66 | private: 67 | Callable _function; 68 | Context _context; 69 | }; 70 | } 71 | 72 | OAG_ASSUME_NONNULL_END 73 | 74 | #endif /* ClosureFunction_hpp */ 75 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Attribute/AttributeID.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // AttributeID.hpp 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef AttributeID_hpp 6 | #define AttributeID_hpp 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace OAG { 13 | class AttributeID final { 14 | public: 15 | enum : uint32_t { 16 | KindMask = 0x00000003, // Bits 0-1 17 | // unused/unknown 0x0000FF00, 18 | }; 19 | enum class Kind: uint8_t { 20 | Direct = 0x0, 21 | Indirect = 0x1, 22 | Null = 0x2, 23 | }; 24 | private: 25 | uint32_t _rawValue; 26 | 27 | OAG_INLINE OAG_CONSTEXPR 28 | const Kind getKind() const OAG_NOEXCEPT { 29 | return Kind(_rawValue & KindMask); 30 | } 31 | public: 32 | OAG_INLINE OAG_CONSTEXPR 33 | AttributeID(OAGAttribute& attribute) OAG_NOEXCEPT: 34 | _rawValue(attribute) {} 35 | 36 | OAG_INLINE OAG_CONSTEXPR 37 | AttributeID(const AttributeID &) noexcept = default; 38 | 39 | OAG_INLINE OAG_CONSTEXPR 40 | AttributeID(AttributeID &&) noexcept = default; 41 | 42 | OAG_INLINE OAG_CONSTEXPR 43 | AttributeID &operator=(const AttributeID &) noexcept = default; 44 | 45 | OAG_INLINE OAG_CONSTEXPR 46 | AttributeID &operator=(AttributeID &&) noexcept = default; 47 | 48 | OAG_INLINE OAG_CONSTEXPR 49 | const bool isDirect() const OAG_NOEXCEPT { 50 | return getKind() == Kind::Direct; 51 | } 52 | 53 | OAG_INLINE OAG_CONSTEXPR 54 | const bool isIndirect() const OAG_NOEXCEPT { 55 | return getKind() == Kind::Indirect; 56 | } 57 | 58 | OAG_INLINE OAG_CONSTEXPR 59 | const bool isNull() const OAG_NOEXCEPT { 60 | return getKind() == Kind::Null; 61 | } 62 | 63 | OAG_INLINE OAG_CONSTEXPR 64 | const void checkIsDirect() const OAG_NOEXCEPT { 65 | if (!isDirect()) { 66 | OAG::precondition_failure("non-direct attribute id: %u", _rawValue); 67 | } 68 | } 69 | }; 70 | static_assert(sizeof(AttributeID) == sizeof(uint32_t)); 71 | } 72 | 73 | #endif /* AttributeID_hpp */ 74 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/OpenAttributeGraph.docc/Runtime/TupleType.md: -------------------------------------------------------------------------------- 1 | # ``TupleType`` 2 | 3 | Runtime support for Swift tuple types with dynamic element access and memory management. 4 | 5 | ## Overview 6 | 7 | `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. 8 | 9 | let tupleType = TupleType([Int.self, String.self, Bool.self]) 10 | let tuple = (42, "Hello", true) 11 | 12 | // Access elements dynamically 13 | let intValue: Int = tuple[0] 14 | let stringValue: String = tuple[1] 15 | let boolValue: Bool = tuple[2] 16 | 17 | TupleType is essential for OpenAttributeGraph's ability to work with heterogeneous data structures while maintaining type safety and efficient memory operations. 18 | 19 | ## Key Features 20 | 21 | - Dynamic tuple creation: Create tuple types from arrays of Swift types 22 | - Element access: Safely access tuple elements by index with type checking 23 | - Memory management: Initialize, copy, and destroy tuple elements safely 24 | - Layout introspection: Query element offsets, sizes, and memory layout 25 | - Buffer operations: Work with raw memory buffers containing tuple data 26 | 27 | ## Usage with Attributes 28 | 29 | TupleType enables OpenAttributeGraph to create attributes that contain heterogeneous data structures, supporting complex reactive computations over tuple-based data. 30 | 31 | ## Topics 32 | 33 | ### Creating Tuple Types 34 | 35 | - ``init(_:)`` 36 | - ``init(_:)-9jmk1`` 37 | - ``init(count:elements:)`` 38 | 39 | ### Type Properties 40 | 41 | - ``type`` 42 | - ``count`` 43 | - ``size`` 44 | - ``isEmpty`` 45 | - ``indices`` 46 | 47 | ### Element Access 48 | 49 | - ``type(at:)`` 50 | - ``elementType(at:)`` 51 | - ``elementSize(at:)`` 52 | - ``elementOffset(at:type:)`` 53 | - ``offset(at:as:)`` 54 | 55 | ### Element Operations 56 | 57 | - ``setElement(in:at:from:options:)`` 58 | - ``getElement(in:at:to:options:)`` 59 | - ``destroy(_:)`` 60 | - ``destroy(_:at:)`` 61 | 62 | ### Copy Options 63 | 64 | - ``CopyOptions`` 65 | 66 | ### Buffer Functions 67 | 68 | - ``withUnsafeTuple(of:count:_:)`` -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGBase.h 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef OAGBase_h 6 | #define OAGBase_h 7 | 8 | #if DEBUG 9 | #define OAG_ASSERTION 10 | #else 11 | #undef OAG_ASSERTION 12 | #endif 13 | 14 | #if __has_attribute(cold) 15 | #define __cold __attribute__((__cold__)) 16 | #else 17 | #define __cold 18 | #endif 19 | 20 | #if __has_attribute(noreturn) 21 | #define __dead2 __attribute__((__noreturn__)) 22 | #else 23 | #define __dead2 24 | #endif 25 | 26 | #if defined(__cplusplus) 27 | #define OAG_NOEXCEPT noexcept 28 | #else 29 | #define OAG_NOEXCEPT 30 | #endif 31 | 32 | #if defined(__GNUC__) 33 | #define OAG_INLINE __inline__ __attribute__((always_inline)) 34 | #elif defined(__cplusplus) 35 | #define OAG_INLINE inline 36 | #else 37 | #define OAG_INLINE 38 | #endif 39 | 40 | #if defined(__cplusplus) 41 | #define OAG_CONSTEXPR constexpr 42 | #else 43 | #define OAG_CONSTEXPR 44 | #endif 45 | 46 | #if __has_include() // Fix conflict define issue of the SDK 47 | #include 48 | #define OAG_COUNTED_BY(N) __counted_by(N) 49 | #else 50 | #if !defined(__counted_by) 51 | #if __has_attribute(__counted_by__) 52 | #define __counted_by(N) __attribute__((__counted_by__(N))) 53 | #else 54 | #define __counted_by(N) 55 | #endif 56 | #endif 57 | #define OAG_COUNTED_BY(N) __counted_by(N) 58 | #endif 59 | 60 | #include "OAGSwiftSupport.h" 61 | #include "OAGTargetConditionals.h" 62 | #include 63 | #include 64 | #include 65 | 66 | #define OAG_ENUM CF_ENUM 67 | #define OAG_CLOSED_ENUM CF_CLOSED_ENUM 68 | #define OAG_OPTIONS CF_OPTIONS 69 | #define OAG_EXTERN_C_BEGIN CF_EXTERN_C_BEGIN 70 | #define OAG_EXTERN_C_END CF_EXTERN_C_END 71 | #define OAG_ASSUME_NONNULL_BEGIN CF_ASSUME_NONNULL_BEGIN 72 | #define OAG_ASSUME_NONNULL_END CF_ASSUME_NONNULL_END 73 | #define OAG_IMPLICIT_BRIDGING_ENABLED CF_IMPLICIT_BRIDGING_ENABLED 74 | #define OAG_IMPLICIT_BRIDGING_DISABLED CF_IMPLICIT_BRIDGING_DISABLED 75 | #define OAG_EXPORT CF_EXPORT 76 | #define OAG_BRIDGED_TYPE CF_BRIDGED_TYPE 77 | 78 | #if OAG_TARGET_OS_DARWIN && __OBJC__ 79 | #define OAG_OBJC_FOUNDATION 1 80 | #else 81 | #define OAG_OBJC_FOUNDATION 0 82 | #endif /* OAG_TARGET_OS_DARWIN && __OBJC__ */ 83 | 84 | #endif /* OAGBase_h */ 85 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCxxTests/DebugServer/DebugServerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DebugServerTests.swift 3 | // OpenAttributeGraphCxxTests 4 | 5 | #if canImport(Darwin) 6 | import Foundation 7 | import OpenAttributeGraphCxx_Private.DebugServer 8 | import Testing 9 | 10 | @MainActor 11 | struct DebugServerTests { 12 | typealias Command = DebugClient.Command 13 | 14 | private func data(for command: Command) throws -> Data{ 15 | let command = ["command": command.rawValue] 16 | return try JSONSerialization.data(withJSONObject: command) 17 | } 18 | 19 | @Test 20 | func commandTest() async throws { 21 | var debugServer = OAG.DebugServer([.valid]) 22 | let cfURL = debugServer.copy_url() 23 | let url = try #require(cfURL) as URL 24 | let components = try #require(URLComponents(url: url, resolvingAgainstBaseURL: false)) 25 | let token = try #require(components.queryItems?.first { $0.name == "token" }?.value.flatMap { UInt32($0) }) 26 | debugServer.run(1) 27 | let client = DebugClient() 28 | let updates = client.connect(to: url) 29 | try await confirmation { confirm in 30 | for try await update in updates { 31 | switch update { 32 | case .ready: 33 | confirm() 34 | for command in Command.allCases { 35 | if command == .graphDescription { 36 | continue 37 | } 38 | try await client.sendMessage( 39 | token: token, 40 | data: data(for: command) 41 | ) 42 | let (_, responseData) = try await client.receiveMessage() 43 | let response = try #require(String(data: responseData, encoding: .utf8)) 44 | #expect(response == command.rawValue) 45 | } 46 | debugServer.shutdown() // TODO: The shutdown should close the connection, but it does not for OAGDebugServer currently. 47 | client.disconnect() 48 | default: 49 | break 50 | } 51 | } 52 | } 53 | } 54 | } 55 | #endif 56 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Graph/Subgraph.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Subgraph.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: WIP 7 | 8 | public import OpenAttributeGraphCxx 9 | 10 | extension Subgraph { 11 | public typealias Flags = AnyAttribute.Flags 12 | 13 | // FIXME 14 | public typealias ChildFlags = AnyAttribute.Flags 15 | } 16 | 17 | extension Subgraph { 18 | public func addObserver(_ observer: @escaping () -> Void) -> Int { 19 | Subgraph.addObserver(self, observer: observer) 20 | } 21 | 22 | public func apply(_ body: () -> Value) -> Value { 23 | #if !os(WASI) 24 | let update = Graph.clearUpdate() 25 | let current = Subgraph.current 26 | defer { 27 | Subgraph.current = current 28 | Graph.setUpdate(update) 29 | } 30 | Subgraph.current = self 31 | return body() 32 | #else 33 | fatalError("upstream SIL Compiler assert issue") 34 | #endif 35 | } 36 | 37 | public func forEach(_ flags: Flags, _ callback: (AnyAttribute) -> Void) { 38 | Subgraph.apply(self, flags: flags, callback: callback) 39 | } 40 | } 41 | 42 | extension Subgraph { 43 | public static func beginTreeElement(value: Attribute, flags: UInt32) { 44 | if shouldRecordTree { 45 | __OAGSubgraphBeginTreeElement(value.identifier, Metadata(Value.self), flags) 46 | } 47 | } 48 | 49 | public static func addTreeValue(_ value: Attribute, forKey key: UnsafePointer, flags: UInt32) { 50 | if shouldRecordTree { 51 | __OAGSubgraphAddTreeValue(value.identifier, Metadata(Value.self), key, flags) 52 | } 53 | } 54 | 55 | public static func endTreeElement(value: Attribute) { 56 | if shouldRecordTree { 57 | __OAGSubgraphEndTreeElement(value.identifier) 58 | } 59 | } 60 | } 61 | 62 | // FIXME: migrate to use @_extern(c, "xx") in Swift 6 63 | extension Subgraph { 64 | @_silgen_name("OAGSubgraphApply") 65 | private static func apply(_ graph: Subgraph, flags: Flags, callback: (AnyAttribute) -> Void) 66 | 67 | @_silgen_name("OAGSubgraphAddObserver") 68 | private static func addObserver(_ graph: Subgraph, observer: @escaping () -> Void) -> Int 69 | } 70 | -------------------------------------------------------------------------------- /Scripts/gen_ag_template.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | # A `realpath` alternative using the default C implementation. 4 | filepath() { 5 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 6 | } 7 | 8 | gen_interface() { 9 | swift build -c release -Xswiftc -emit-module-interface -Xswiftc -enable-library-evolution -Xswiftc -no-verify-emitted-module-interface -Xswiftc -package-name -Xswiftc OpenAttributeGraph -Xswiftc -Osize 10 | 11 | mkdir -p .ag_template 12 | cp .build/release/Modules/OpenAttributeGraph.swiftinterface .ag_template/template.swiftinterface 13 | 14 | sed -i '' '1,4d' .ag_template/template.swiftinterface 15 | sed -i '' 's/@_exported public import OpenAttributeGraphCxx/@_exported public import AttributeGraph/g' .ag_template/template.swiftinterface 16 | sed -i '' 's/OpenAttributeGraphCxx\.//g' .ag_template/template.swiftinterface 17 | sed -i '' 's/OpenAttributeGraph/AttributeGraph/g' .ag_template/template.swiftinterface 18 | sed -i '' 's/OPENATTRIBUTEGRAPH/ATTRIBUTEGRAPH/g' .ag_template/template.swiftinterface 19 | sed -i '' 's/OAG/AG/g' .ag_template/template.swiftinterface 20 | 21 | echo "Generated template.swiftinterface successfully" 22 | } 23 | 24 | gen_header() { 25 | mkdir -p .ag_template/Headers 26 | 27 | cp -r Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/* .ag_template/Headers/ 28 | 29 | # Rename files from OAGxx to AGxx and OpenAttributeGraphxx to AttributeGraphxx 30 | find .ag_template/Headers -name "OAG*" -type f | while read file; do 31 | new_name=$(echo "$file" | sed 's/OAG/AG/g') 32 | mv "$file" "$new_name" 33 | done 34 | 35 | find .ag_template/Headers -name "OpenAttributeGraph*" -type f | while read file; do 36 | new_name=$(echo "$file" | sed 's/OpenAttributeGraph/AttributeGraph/g') 37 | mv "$file" "$new_name" 38 | done 39 | 40 | # Update content in all header files 41 | find .ag_template/Headers -name "*.h" -type f | while read file; do 42 | sed -i '' 's/OpenAttributeGraphCxx/AttributeGraph/g' "$file" 43 | sed -i '' 's/OpenAttributeGraph/AttributeGraph/g' "$file" 44 | sed -i '' 's/OPENATTRIBUTEGRAPH/ATTRIBUTEGRAPH/g' "$file" 45 | sed -i '' 's/OAG/AG/g' "$file" 46 | done 47 | 48 | echo "Generated template headers successfully" 49 | } 50 | 51 | OPENATTRIBUTEGRAPH_ROOT="$(dirname $(dirname $(filepath $0)))" 52 | 53 | cd $OPENATTRIBUTEGRAPH_ROOT 54 | 55 | gen_interface 56 | gen_header 57 | -------------------------------------------------------------------------------- /CLAUDE.md: -------------------------------------------------------------------------------- 1 | # OpenAttributeGraph Project Guide 2 | 3 | ## Project Overview 4 | OpenAttributeGraph is a Swift package that provides attribute graph functionality, serving as a foundation for OpenSwiftUI project. It interfaces with DarwinPrivateFrameworks for compatibility testing. 5 | 6 | ## Development Workflow 7 | 8 | ### 1. Make Changes and Commit 9 | - Implement your feature or fix 10 | - Test locally 11 | - Commit changes with descriptive messages 12 | 13 | ### 2. (Optional) Compatibility Testing 14 | If changes affect the interface with DarwinPrivateFrameworks: 15 | ```bash 16 | # Generate AG template 17 | Scripts/gen_ag_template.sh 18 | ` 19 | # Update code in ../DarwinPrivateFramework from .ag_template 20 | 21 | # Set useLocalDeps to true in Package.swift 22 | xed -l -c 's/let useLocalDeps = envEnable("OPENATTRIBUTEGRAPH_USE_LOCAL_DEPS")/let useLocalDeps = true/' Package.swift 23 | 24 | # Build and test with both compatibility modes: 25 | OPENATTRIBUTEGRAPH_COMPATIBILITY_TEST=0 swift build 26 | OPENATTRIBUTEGRAPH_COMPATIBILITY_TEST=1 swift build 27 | ``` 28 | 29 | ### 3. Create DarwinPrivateFramework PR 30 | After testing, discard local changes from step 2: 31 | ```bash 32 | # Discard any local testing changes 33 | git checkout -- Package.swift 34 | 35 | # Create PR for DarwinPrivateFramework 36 | Scripts/bump_ag_pr.sh 37 | ``` 38 | 39 | ### 4. Update Dependencies 40 | After the DarwinPrivateFramework PR is merged: 41 | ```bash 42 | # Update package dependencies 43 | swift package update DarwinPrivateFramework 44 | 45 | # Commit the updated Package.resolved 46 | git add Package.resolved 47 | git commit -m "Update DarwinPrivateFrameworks dependency" 48 | ``` 49 | 50 | ### 5. Create Project PR 51 | ```bash 52 | # Create PR for the current branch 53 | gh pr create --base main --head 54 | ``` 55 | 56 | ## Key Scripts 57 | - `Scripts/gen_ag_template.sh` - Generates AG template for compatibility testing 58 | - `Scripts/bump_ag_pr.sh` - Creates PR for DarwinPrivateFramework updates 59 | 60 | ## Environment Variables 61 | - `OPENATTRIBUTEGRAPH_COMPATIBILITY_TEST=0` - Test without compatibility mode 62 | - `OPENATTRIBUTEGRAPH_COMPATIBILITY_TEST=1` - Test with compatibility mode 63 | 64 | ## Important Notes 65 | - Always test compatibility when changing interfaces 66 | - Ensure DarwinPrivateFramework PR is merged before creating main project PR 67 | - Keep Package.resolved updated after dependency changes -------------------------------------------------------------------------------- /.github/workflows/ios.yml: -------------------------------------------------------------------------------- 1 | name: iOS 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | ios_test: 11 | name: Execute tests on iOS 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | os: [macos-15] 16 | xcode-version: ["16.4"] # Swift 6.1.2 17 | ios-version: ["18.5"] 18 | include: 19 | - ios-version: "18.5" 20 | ios-simulator-name: "iPhone 16 Pro" 21 | runs-on: ${{ matrix.os }} 22 | env: 23 | OPENATTRIBUTEGRAPH_WERROR: 1 24 | OPENATTRIBUTEGRAPH_ATTRIBUTEGRAPH: 0 25 | OPENATTRIBUTEGRAPH_COMPATIBILITY_TEST: 0 26 | OPENATTRIBUTEGRAPH_USE_LOCAL_DEPS: 1 27 | OPENATTRIBUTEGRAPH_TARGET_RELEASE: 2024 28 | DARWINPRIVATEFRAMEWORKS_TARGET_RELEASE: 2024 29 | GH_TOKEN: ${{ github.token }} 30 | steps: 31 | - uses: actions/checkout@v4 32 | - name: Setup Xcode 33 | uses: OpenSwiftUIProject/OpenSwiftUI/.github/actions/setup-xcode@main 34 | with: 35 | xcode-version: ${{ matrix.xcode-version }} 36 | - name: Swift version 37 | run: swift --version 38 | - name: Set up build environment 39 | run: Scripts/CI/darwin_setup_build.sh 40 | shell: bash 41 | - name: Build in debug mode on iOS 42 | run: | 43 | xcodebuild build \ 44 | -scheme OpenAttributeGraph-Package \ 45 | -configuration Debug \ 46 | -destination "platform=iOS Simulator,OS=${{ matrix.ios-version }},name=${{ matrix.ios-simulator-name }}" \ 47 | -derivedDataPath .build-debug \ 48 | -skipMacroValidation \ 49 | -skipPackagePluginValidation \ 50 | OTHER_SWIFT_FLAGS="-warnings-as-errors" 51 | - name: Build and run tests in debug mode with coverage on iOS Simulator 52 | run: | 53 | xcodebuild test \ 54 | -scheme OpenAttributeGraph-Package \ 55 | -configuration Debug \ 56 | -destination "platform=iOS Simulator,OS=${{ matrix.ios-version }},name=${{ matrix.ios-simulator-name }}" \ 57 | -enableCodeCoverage=YES \ 58 | -derivedDataPath .build-test-debug \ 59 | -skipPackagePluginValidation \ 60 | -skipMacroValidation 61 | # OTHER_SWIFT_FLAGS="-warnings-as-errors" Conflicting options '-warnings-as-errors' and '-suppress-warnings' 62 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Vector/realloc_vector.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // realloc_vector.cpp 3 | // OpenAttributeGraphCxx 4 | 5 | #include 6 | #include 7 | 8 | #if OAG_TARGET_OS_DARWIN 9 | #include 10 | #else 11 | #include 12 | #endif /* OAG_TARGET_OS_DARWIN */ 13 | 14 | template 15 | void *_Nullable OAG::details::realloc_vector(void* ptr, T& size, T new_size) { 16 | if (new_size == 0) { 17 | size = 0; 18 | free(ptr); 19 | return nullptr; 20 | } else { 21 | size_t msize = malloc_good_size(new_size * Alignment); 22 | if (size == msize / Alignment) { 23 | return ptr; 24 | } else { 25 | void *new_ptr = realloc(ptr, msize); 26 | if (new_ptr == nullptr) { 27 | OAG::precondition_failure("memory allocation failed"); 28 | } else { 29 | size = msize / Alignment; 30 | return new_ptr; 31 | } 32 | } 33 | } 34 | } 35 | 36 | template 37 | void *_Nullable OAG::details::realloc_vector(void* src, void* dst, T dstSize, T& size, T newSize) { 38 | if (newSize < dstSize) { 39 | if (src == dst) { 40 | return src; 41 | } else { 42 | memcpy(dst, src, newSize * Alignment); 43 | size = dstSize; 44 | free(src); 45 | return dst; 46 | } 47 | } else { 48 | size_t msize = malloc_good_size(newSize * Alignment); 49 | if (size == msize / Alignment) { 50 | return src; 51 | } else { 52 | if (src == dst) { 53 | void *new_ptr = malloc(msize); 54 | if (new_ptr == nullptr) { 55 | OAG::precondition_failure("memory allocation failed"); 56 | } else { 57 | memcpy(new_ptr, src, size * Alignment); 58 | size = msize / Alignment; 59 | return new_ptr; 60 | } 61 | } else { 62 | void *new_ptr = realloc(src, msize); 63 | if (new_ptr == nullptr) { 64 | OAG::precondition_failure("memory allocation failed"); 65 | } else { 66 | size = msize / Alignment; 67 | return new_ptr; 68 | } 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCxxTests/Util/ForwardListTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ForwardListTests.swift 3 | // OpenAttributeGraphCxxTests 4 | 5 | import OpenAttributeGraphCxx_Private.Util 6 | import Testing 7 | 8 | @Suite("List tests") 9 | struct ForwardListTests { 10 | 11 | @Test("Initialize empty list") 12 | @available(iOS 16.4, *) 13 | func initEmpty() { 14 | let list = util.UInt64ForwardList.create() 15 | defer { 16 | util.UInt64ForwardList.destroy(list) 17 | } 18 | 19 | #expect(list.empty()) 20 | } 21 | 22 | @Test("Push element") 23 | @available(iOS 16.4, *) 24 | func pushElement() { 25 | let list = util.UInt64ForwardList.create() 26 | defer { 27 | util.UInt64ForwardList.destroy(list) 28 | } 29 | 30 | list.push_front(1) 31 | 32 | #expect(list.empty() == false) 33 | 34 | let front = list.front() 35 | #expect(front == 1) 36 | } 37 | 38 | @Test("Push multiple elements") 39 | @available(iOS 16.4, *) 40 | func pushMultipleElements() { 41 | let list = util.UInt64ForwardList.create() 42 | defer { 43 | util.UInt64ForwardList.destroy(list) 44 | } 45 | 46 | list.push_front(1) 47 | list.push_front(2) 48 | list.push_front(3) 49 | 50 | let front = list.front() 51 | #expect(front == 3) 52 | } 53 | 54 | @Test("Remove element") 55 | @available(iOS 16.4, *) 56 | func removeElement() { 57 | let list = util.UInt64ForwardList.create() 58 | defer { 59 | util.UInt64ForwardList.destroy(list) 60 | } 61 | 62 | list.push_front(1) 63 | list.push_front(2) 64 | list.push_front(3) 65 | list.pop_front() 66 | 67 | let front = list.front() 68 | #expect(front == 2) 69 | } 70 | 71 | @Test("Sequential operations") 72 | @available(iOS 16.4, *) 73 | func sequentialOperations() { 74 | let list = util.UInt64ForwardList.create() 75 | defer { 76 | util.UInt64ForwardList.destroy(list) 77 | } 78 | 79 | // Add multiple elements 80 | for i in 0..<5 { 81 | list.push_front(UInt64(i)) 82 | } 83 | 84 | // Remove all elements and verify order (LIFO - last in, first out) 85 | for i in (0..<5).reversed() { 86 | #expect(!list.empty()) 87 | #expect(list.front() == UInt64(i)) 88 | list.pop_front() 89 | } 90 | 91 | #expect(list.empty()) 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Graph/Graph.mm: -------------------------------------------------------------------------------- 1 | // 2 | // Graph.mm 3 | // OpenAttributeGraphCxx 4 | 5 | #include 6 | #include 7 | 8 | #if OAG_OBJC_FOUNDATION 9 | #include 10 | #include 11 | 12 | void OAG::Graph::write_to_file(const Graph * _Nullable graph, const char * _Nullable name, uint8_t options) OAG_NOEXCEPT { 13 | @autoreleasepool { 14 | NSDictionary *options_dict = @{ 15 | (__bridge NSString *)OAGDescriptionFormat: (__bridge NSString *)OAGDescriptionFormatDictionary, 16 | (__bridge NSString *)OAGDescriptionIncludeValues: @((options & 1) == 0), 17 | (__bridge NSString *)OAGDescriptionAllGraphs: @(graph == nil) 18 | }; 19 | NSString *description = (__bridge NSString *)Graph::description(graph, options_dict); 20 | if (description == nil) { 21 | return; 22 | } 23 | const char *cstring_name = name ?: "graph.ag-gzon"; 24 | 25 | NSData *data = [NSJSONSerialization dataWithJSONObject:description options:0 error:nil]; 26 | NSString *file_path = [NSString stringWithUTF8String:cstring_name]; 27 | if (cstring_name[0] != '/') { 28 | file_path = [NSTemporaryDirectory() stringByAppendingPathComponent:file_path]; 29 | } 30 | NSError *error = nil; 31 | BOOL success = YES; 32 | if ([file_path.pathExtension isEqualToString:@"ag-gzon"]) { 33 | gzFile file = gzopen(file_path.fileSystemRepresentation, "wb"); 34 | if (file != NULL) { 35 | const char *bytes = (const char *)[data bytes]; 36 | NSUInteger remaining = [data length]; 37 | while (remaining != 0) { 38 | int bytes_written = gzwrite(file, bytes, (unsigned int)remaining); 39 | if (bytes_written <= 0) { 40 | success = NO; 41 | break; 42 | } 43 | bytes += bytes_written; 44 | remaining -= bytes_written; 45 | } 46 | gzclose(file); 47 | } 48 | } else { 49 | success = [data writeToFile:file_path options:0 error:&error]; 50 | } 51 | if (success) { 52 | fprintf(stderr, "Wrote graph data to \"%s\".\n", file_path.UTF8String); 53 | } else { 54 | fprintf(stderr, "Unable to write to \"%s\": %s\n", file_path.UTF8String, error.description.UTF8String); 55 | } 56 | } 57 | } 58 | 59 | #endif /* OAG_OBJC_FOUNDATION */ 60 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Attribute/RuleContext/AnyRuleContext.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnyRuleContext.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: Complete 7 | 8 | public import OpenAttributeGraphCxx 9 | 10 | @frozen 11 | public struct AnyRuleContext: Equatable { 12 | public var attribute: AnyAttribute 13 | 14 | public init(attribute: AnyAttribute) { 15 | self.attribute = attribute 16 | } 17 | 18 | public init(_ context: RuleContext) { 19 | attribute = context.attribute.identifier 20 | } 21 | 22 | public subscript(attribute: Attribute) -> V { 23 | unsafeAddress { 24 | OAGGraphGetInputValue(self.attribute, input: attribute.identifier, type: V.self) 25 | .value 26 | .assumingMemoryBound(to: V.self) 27 | } 28 | } 29 | 30 | public subscript(weakAttribute: WeakAttribute) -> V? { 31 | weakAttribute.attribute.map { attribute in 32 | OAGGraphGetInputValue(self.attribute, input: attribute.identifier, type: V.self) 33 | .value 34 | .assumingMemoryBound(to: V.self) 35 | .pointee 36 | } 37 | } 38 | 39 | public subscript(optionalAttribute: OptionalAttribute) -> V? { 40 | optionalAttribute.attribute.map { attribute in 41 | OAGGraphGetInputValue(self.attribute, input: attribute.identifier, type: V.self) 42 | .value 43 | .assumingMemoryBound(to: V.self) 44 | .pointee 45 | } 46 | } 47 | 48 | public func valueAndFlags(of input: Attribute, options: OAGValueOptions = []) -> (value: V, flags: OAGChangedValueFlags) { 49 | let value = OAGGraphGetInputValue(attribute, input: input.identifier, options: options, type: V.self) 50 | return ( 51 | value.value.assumingMemoryBound(to: V.self).pointee, 52 | value.flags 53 | ) 54 | } 55 | 56 | public func changedValue(of input: Attribute, options: OAGValueOptions = []) -> (value: V, changed: Bool) { 57 | let value = OAGGraphGetInputValue(attribute, input: input.identifier, options: options, type: V.self) 58 | return ( 59 | value.value.assumingMemoryBound(to: V.self).pointee, 60 | value.flags.contains(.changed) 61 | ) 62 | } 63 | 64 | public func update(body: () -> Void) { 65 | OAGGraphWithUpdate(attribute, body: body) 66 | } 67 | 68 | public func unsafeCast(to _: V.Type) -> RuleContext { 69 | RuleContext(attribute: Attribute(identifier: attribute)) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Runtime/Metadata.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Metadata.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: WIP 7 | 8 | public import OpenAttributeGraphCxx 9 | #if canImport(ObjectiveC) 10 | import Foundation 11 | #endif 12 | 13 | @_silgen_name("OAGTypeApplyFields") 14 | private func OAGTypeApplyFields( 15 | of type: Any.Type, 16 | body: (UnsafePointer, Int, Any.Type) -> Void 17 | ) 18 | 19 | @_silgen_name("OAGTypeApplyFields2") 20 | private func OAGTypeApplyFields2( 21 | of type: Any.Type, 22 | options: Metadata.ApplyOptions, 23 | body: (UnsafePointer, Int, Any.Type) -> Bool 24 | ) -> Bool 25 | 26 | public func forEachField( 27 | of type: Any.Type, 28 | do body: (UnsafePointer, Int, Any.Type) -> Void 29 | ) { 30 | OAGTypeApplyFields(of: type, body: body) 31 | } 32 | 33 | extension Metadata: Swift.Hashable, Swift.CustomStringConvertible { 34 | /// Creates metadata from a Swift type. 35 | /// 36 | /// - Parameter type: The Swift type to create metadata for 37 | public init(_ type: any Any.Type) { 38 | self.init(rawValue: unsafeBitCast(type, to: UnsafePointer<_Metadata>.self)) 39 | } 40 | 41 | /// The Swift type represented by this metadata. 42 | public var type: any Any.Type { 43 | unsafeBitCast(rawValue, to: Any.Type.self) 44 | } 45 | 46 | public var description: String { 47 | #if canImport(ObjectiveC) 48 | __OAGTypeDescription(self) as NSString as String 49 | #else 50 | fatalError("Unimplemented") 51 | #endif 52 | } 53 | 54 | public func forEachField( 55 | options: ApplyOptions, 56 | do body: (UnsafePointer, Int, Any.Type) -> Bool 57 | ) -> Bool { 58 | OAGTypeApplyFields2(of: type, options: options, body: body) 59 | } 60 | } 61 | 62 | extension Signature: Swift.Equatable { 63 | public static func == (_ lhs: Signature, _ rhs: Signature) -> Bool { 64 | return lhs.bytes.0 == rhs.bytes.0 && lhs.bytes.1 == rhs.bytes.1 65 | && lhs.bytes.2 == rhs.bytes.2 && lhs.bytes.3 == rhs.bytes.3 66 | && lhs.bytes.4 == rhs.bytes.4 && lhs.bytes.5 == rhs.bytes.5 67 | && lhs.bytes.6 == rhs.bytes.6 && lhs.bytes.7 == rhs.bytes.7 68 | && lhs.bytes.8 == rhs.bytes.8 && lhs.bytes.9 == rhs.bytes.9 69 | && lhs.bytes.10 == rhs.bytes.10 && lhs.bytes.11 == rhs.bytes.11 70 | && lhs.bytes.12 == rhs.bytes.12 && lhs.bytes.13 == rhs.bytes.13 71 | && lhs.bytes.14 == rhs.bytes.14 && lhs.bytes.15 == rhs.bytes.15 72 | && lhs.bytes.16 == rhs.bytes.16 && lhs.bytes.17 == rhs.bytes.17 73 | && lhs.bytes.18 == rhs.bytes.18 && lhs.bytes.19 == rhs.bytes.19 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCompatibilityTests/Attribute/Attribute/AttributeCompatibilityTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AttributeCompatibilityTests.swift 3 | // OpenAttributeGraphCompatibilityTests 4 | 5 | import Testing 6 | 7 | #if canImport(Darwin) 8 | @MainActor 9 | @Suite(.disabled(if: !compatibilityTestEnabled, "Attribute is not implemented"), .graphScope) 10 | struct AttributeCompatibilityTests { 11 | @Test 12 | func initWithValue() { 13 | let intAttribute = Attribute(value: 0) 14 | #expect(intAttribute.value == 0) 15 | } 16 | 17 | @Test 18 | func hashableAndEquatable() { 19 | let a = Attribute(identifier: .nil) 20 | let b = Attribute(identifier: .nil) 21 | #expect(a == b) 22 | #expect(a.hashValue == b.hashValue) 23 | } 24 | 25 | @Test 26 | func propertyWrapper() { 27 | @Attribute(value: 0) var value 28 | #expect(value == 0) 29 | value = 3 30 | #expect(value == 3) 31 | #expect(_value.setValue(4) == true) 32 | #expect(value == 4) 33 | let newAttribute = $value 34 | value = 5 35 | #expect(newAttribute.wrappedValue == 5) 36 | } 37 | 38 | @Test(arguments: [ 39 | Triple(first: 0, second: 1, third: 2), 40 | Triple(first: 3, second: 4, third: 5), 41 | ]) 42 | func attributeWithSubscript(_ value: Triple) { 43 | let attribute = Attribute(value: value) 44 | let offsetValue = attribute[offset: { _ in 45 | PointerOffset, Int>(byteOffset: 8) 46 | }] 47 | #expect(offsetValue.wrappedValue == value.second) 48 | #expect(attribute.first.wrappedValue == value.first) 49 | #expect(attribute[keyPath: \.third].wrappedValue == value.third) 50 | } 51 | 52 | @Test 53 | func value() { 54 | let attribute = Attribute(value: 5) 55 | #expect(attribute.hasValue == true) 56 | #expect(attribute.changedValue(options: []) == (5, false)) 57 | 58 | #expect(attribute.setValue(3) == true) 59 | #expect(attribute.changedValue(options: []) == (3, false)) // TODO: How to test for changed == true 60 | 61 | // Unknown effect and untested. 62 | // Just add here for linkage test 63 | attribute.updateValue() 64 | attribute.prefetchValue() 65 | attribute.invalidateValue() 66 | } 67 | 68 | @Test 69 | func mutateBodyAPI() { 70 | let attribute = Attribute(value: 5) 71 | attribute.mutateBody(as: External.self, invalidating: true) { _ in 72 | 73 | } 74 | } 75 | 76 | @Test 77 | func flagSetter() { 78 | let attribute = Attribute(value: ()) 79 | attribute.flags = .init(rawValue: 1) 80 | #expect(attribute.flags == .init(rawValue: 1)) 81 | } 82 | } 83 | #endif 84 | -------------------------------------------------------------------------------- /Tests/OpenAttributeGraphCxxTests/Util/HeapTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HeapTests.swift 3 | // OpenAttributeGraphCxxTests 4 | 5 | import OpenAttributeGraphCxx_Private.Util 6 | import Testing 7 | 8 | @Suite("Heap tests") 9 | struct HeapTests { 10 | 11 | let nodeSize = 16 12 | 13 | @Test("Initializing with default arguments") 14 | @available(iOS 16.4, *) 15 | func initDefault() { 16 | let heap = util.Heap.create(nil, 0, 0) 17 | defer { 18 | util.Heap.destroy(heap) 19 | } 20 | 21 | #expect(heap.capacity() == 0) 22 | #expect(heap.increment() == 0x2000) 23 | #expect(heap.num_nodes() == 0) 24 | } 25 | 26 | @Test("Initializing with custom increment") 27 | @available(iOS 16.4, *) 28 | func initWithCustomIncrement() { 29 | let customIncrement = 4096 30 | let heap = util.Heap.create(nil, 0, customIncrement) 31 | defer { 32 | util.Heap.destroy(heap) 33 | } 34 | 35 | #expect(heap.capacity() == 0) 36 | #expect(heap.increment() == customIncrement) 37 | #expect(heap.num_nodes() == 0) 38 | } 39 | 40 | @Test("Creating heap with initial buffer") 41 | @available(iOS 16.4, *) 42 | func createWithInitialBuffer() { 43 | var buffer = Array(repeating: 0, count: 1024) 44 | 45 | let heap = buffer.withUnsafeMutableBytes { bufferPtr in 46 | let charPtr = bufferPtr.bindMemory(to: CChar.self) 47 | return util.Heap.create(charPtr.baseAddress, 1024, 2048) 48 | } 49 | defer { 50 | util.Heap.destroy(heap) 51 | } 52 | 53 | #expect(heap.capacity() == 1024) 54 | #expect(heap.increment() == 2048) 55 | #expect(heap.num_nodes() == 0) 56 | } 57 | 58 | @Test("Reset heap functionality") 59 | @available(iOS 16.4, *) 60 | func resetHeap() { 61 | let heap = util.Heap.create(nil, 0, 1024) 62 | defer { 63 | util.Heap.destroy(heap) 64 | } 65 | 66 | // Reset heap to different configuration 67 | heap.reset(nil, 0) 68 | 69 | // Verify heap properties after reset 70 | #expect(heap.increment() == 1024) 71 | #expect(heap.capacity() == 0) 72 | #expect(heap.num_nodes() == 0) 73 | } 74 | 75 | @Test("Print heap debug information") 76 | @available(iOS 16.4, *) 77 | func printHeapInfo() { 78 | let heap = util.Heap.create(nil, 0, 1024) 79 | defer { 80 | util.Heap.destroy(heap) 81 | } 82 | 83 | // Test that print method can be called without crashing 84 | heap.print() 85 | 86 | // Verify heap is still functional after print 87 | #expect(heap.increment() == 1024) 88 | #expect(heap.num_nodes() == 0) 89 | #expect(heap.capacity() == 0) 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Runtime/metadata.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // metadata.hpp 3 | // OpenAttributeGraphCxx 4 | // 5 | // Audited for iOS 18.0 6 | // Status: WIP 7 | 8 | #ifndef metadata_hpp 9 | #define metadata_hpp 10 | 11 | #include 12 | 13 | #ifdef OPENATTRIBUTEGRAPH_SWIFT_TOOLCHAIN_SUPPORTED 14 | #include 15 | #include 16 | using namespace swift; 17 | #endif /* OPENATTRIBUTEGRAPH_SWIFT_TOOLCHAIN_SUPPORTED */ 18 | 19 | namespace OAG { 20 | namespace swift { 21 | #ifdef OPENATTRIBUTEGRAPH_SWIFT_TOOLCHAIN_SUPPORTED 22 | class metadata: public Metadata { 23 | public: 24 | OAG_INLINE OAG_CONSTEXPR 25 | Metadata const* getType() const OAG_NOEXCEPT { 26 | return this; 27 | } 28 | 29 | OAG_INLINE OAG_CONSTEXPR 30 | TypeNamePair const name(bool qualified) const OAG_NOEXCEPT { 31 | return swift_getTypeName(getType(), qualified); 32 | } 33 | 34 | OAG_INLINE OAG_CONSTEXPR 35 | MetadataKind const getKind() const OAG_NOEXCEPT { 36 | return getType()->getKind(); 37 | } 38 | 39 | OAG_INLINE OAG_CONSTEXPR 40 | TypeContextDescriptor const* descriptor() const OAG_NOEXCEPT { 41 | switch (getKind()) { 42 | case MetadataKind::Class: { 43 | const auto cls = static_cast(getType()); 44 | // We may build this with a newer OS SDK but run on old OS. 45 | // So instead of using `isTypeMetadata` / `(Data & SWIFT_CLASS_IS_SWIFT_MASK)`, 46 | // we manully use 3 here to check isTypeMetadata 47 | if ((cls->Data & 3) == 0) return nullptr; 48 | return cls->getDescription(); 49 | } 50 | case MetadataKind::Struct: 51 | case MetadataKind::Enum: 52 | case MetadataKind::Optional: { 53 | return static_cast *>(getType())->Description; 54 | } 55 | default: 56 | return nullptr; 57 | } 58 | } 59 | 60 | OAG_INLINE OAG_CONSTEXPR 61 | TypeContextDescriptor const* nominal_descriptor() const OAG_NOEXCEPT { 62 | auto descriptor = this->descriptor(); 63 | if (descriptor == nullptr) { 64 | return nullptr; 65 | } 66 | switch(descriptor->getKind()) { 67 | case ContextDescriptorKind::Struct: 68 | case ContextDescriptorKind::Enum: 69 | return descriptor; 70 | default: 71 | return nullptr; 72 | } 73 | } 74 | 75 | void append_description(CFMutableStringRef description) const OAG_NOEXCEPT; 76 | }; /* OAG::swift::metadata */ 77 | #else 78 | class metadata {}; 79 | #endif /* OPENATTRIBUTEGRAPH_SWIFT_TOOLCHAIN_SUPPORTED */ 80 | } /* OAG::swift */ 81 | } /* OAG */ 82 | 83 | #endif /* metadata_hpp */ 84 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Attribute/Rule/StatefulRule.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StatefulRule.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: Complete 7 | 8 | public import OpenAttributeGraphCxx 9 | 10 | /// A protocol for defining computed attributes that maintain state between evaluations. 11 | /// 12 | /// `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. 13 | /// 14 | /// struct CounterRule: StatefulRule { 15 | /// typealias Value = Int 16 | /// private var counter = 0 17 | /// 18 | /// mutating func updateValue() { 19 | /// counter += 1 20 | /// value = counter 21 | /// } 22 | /// } 23 | /// 24 | /// Unlike ``Rule``, `StatefulRule` allows mutation through the `updateValue()` method and provides direct access to the current value through the `value` property. 25 | /// 26 | /// ## Key Features 27 | /// 28 | /// - Mutable state: Rules can maintain and modify internal state 29 | /// - Direct value access: Read and write the current value directly 30 | /// - Context access: Access to rule evaluation context and attribute 31 | /// - Lifecycle control: Manual control over when and how values update 32 | /// 33 | /// ## Usage Pattern 34 | /// 35 | /// StatefulRule is ideal for scenarios where you need to: 36 | /// - Accumulate values over time 37 | /// - Maintain counters or timers 38 | /// - Implement complex state machines 39 | /// - Cache expensive computations with custom invalidation 40 | public protocol StatefulRule: _AttributeBody { 41 | associatedtype Value 42 | static var initialValue: Value? { get } 43 | mutating func updateValue() 44 | } 45 | 46 | // MARK: - StatefulRule Protocol default implementation 47 | 48 | extension StatefulRule { 49 | public static var initialValue: Value? { nil } 50 | 51 | public static func _update(_ pointer: UnsafeMutableRawPointer, attribute _: AnyAttribute) { 52 | pointer.assumingMemoryBound(to: Self.self) 53 | .pointee 54 | .updateValue() 55 | } 56 | 57 | public static func _updateDefault(_: UnsafeMutableRawPointer) { 58 | guard let initialValue else { 59 | return 60 | } 61 | withUnsafePointer(to: initialValue) { value in 62 | Graph.setOutputValue(value) 63 | } 64 | } 65 | } 66 | 67 | // MARK: - StatefulRule extension 68 | 69 | extension StatefulRule { 70 | public var attribute: Attribute { 71 | Attribute(identifier: AnyAttribute.current!) 72 | } 73 | 74 | public var context: RuleContext { 75 | RuleContext(attribute: attribute) 76 | } 77 | 78 | public var value: Value { 79 | unsafeAddress { Graph.outputValue()! } 80 | nonmutating set { context.value = newValue } 81 | } 82 | 83 | public var hasValue: Bool { context.hasValue } 84 | } 85 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGComparison.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGComparison.h 3 | // OpenAttributeGraphCxx 4 | // 5 | // Audited for 6.5.1 6 | // Status: Complete 7 | 8 | #ifndef OAGComparison_h 9 | #define OAGComparison_h 10 | 11 | #include 12 | #include 13 | 14 | OAG_ASSUME_NONNULL_BEGIN 15 | 16 | OAG_IMPLICIT_BRIDGING_ENABLED 17 | 18 | OAG_EXTERN_C_BEGIN 19 | 20 | typedef struct OAG_SWIFT_NAME(FieldRange) OAGFieldRange { 21 | size_t offset; 22 | size_t size; 23 | } OAGFieldRange; 24 | 25 | typedef const void *OAGComparisonState OAG_SWIFT_STRUCT OAG_SWIFT_NAME(ComparisonState); 26 | 27 | OAG_EXPORT 28 | OAG_REFINED_FOR_SWIFT 29 | const void *OAGComparisonStateGetDestination(OAGComparisonState state) OAG_SWIFT_NAME(getter:OAGComparisonState.destination(self:)); 30 | 31 | OAG_EXPORT 32 | OAG_REFINED_FOR_SWIFT 33 | const void *OAGComparisonStateGetSource(OAGComparisonState state) OAG_SWIFT_NAME(getter:OAGComparisonState.source(self:)); 34 | 35 | OAG_EXPORT 36 | OAG_REFINED_FOR_SWIFT 37 | OAGFieldRange OAGComparisonStateGetFieldRange(OAGComparisonState state) OAG_SWIFT_NAME(getter:OAGComparisonState.fieldRange(self:)); 38 | 39 | OAG_EXPORT 40 | OAG_REFINED_FOR_SWIFT 41 | OAGTypeID OAGComparisonStateGetFieldType(OAGComparisonState state) OAG_SWIFT_NAME(getter:OAGComparisonState.fieldType(self:)); 42 | 43 | typedef OAG_ENUM(uint8_t, OAGComparisonMode) { 44 | OAGComparisonModeBitwise = 0, 45 | OAGComparisonModeIndirect = 1, 46 | OAGComparisonModeEquatableUnlessPOD = 2, 47 | OAGComparisonModeEquatableAlways = 3, 48 | } OAG_SWIFT_NAME(ComparisonMode); 49 | 50 | typedef OAG_OPTIONS(uint32_t, OAGComparisonOptions) { 51 | OAGComparisonOptionsComparisonModeBitwise = 0, 52 | OAGComparisonOptionsComparisonModeIndirect = 1, 53 | OAGComparisonOptionsComparisonModeEquatableUnlessPOD = 2, 54 | OAGComparisonOptionsComparisonModeEquatableAlways = 3, 55 | OAGComparisonOptionsComparisonModeMask = 0xff, 56 | 57 | OAGComparisonOptionsCopyOnWrite = 1 << 8, 58 | OAGComparisonOptionsFetchLayoutsSynchronously = 1 << 9, 59 | OAGComparisonOptionsTraceCompareFailed = 1ul << 31, // -1 signed int 60 | } OAG_SWIFT_NAME(ComparisonOptions); 61 | 62 | OAG_EXPORT 63 | OAG_REFINED_FOR_SWIFT 64 | bool OAGCompareValues(const void *lhs, 65 | const void *rhs, 66 | OAGTypeID type_id, 67 | OAGComparisonOptions options); 68 | 69 | OAG_EXPORT 70 | OAG_REFINED_FOR_SWIFT 71 | const unsigned char *_Nullable OAGPrefetchCompareValues(OAGTypeID type_id, 72 | OAGComparisonOptions options, 73 | uint32_t priority); 74 | 75 | OAG_EXPORT 76 | OAG_REFINED_FOR_SWIFT 77 | void OAGOverrideComparisonForTypeDescriptor(void *descriptor, OAGComparisonMode mode); 78 | 79 | OAG_EXTERN_C_END 80 | 81 | OAG_IMPLICIT_BRIDGING_DISABLED 82 | 83 | OAG_ASSUME_NONNULL_END 84 | 85 | #endif /* OAGComparison_h */ 86 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/Util/Heap.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Heap.cpp 3 | // OpenAttributeGraphCxx 4 | // 5 | // Status: Complete 6 | // Modified based Compute code 7 | 8 | #include 9 | #include 10 | 11 | namespace util { 12 | 13 | constexpr size_t default_increment = 0x2000; 14 | 15 | Heap *Heap::create(char *_Nullable start, size_t capacity, size_t increment) { 16 | return new Heap(start, capacity, increment); 17 | } 18 | 19 | void Heap::destroy(Heap *value) { delete value; } 20 | 21 | Heap::Heap(char *start, size_t capacity, size_t increment) { 22 | // enforce minimum but treat 0 as the default 23 | size_t effective_increment = increment > 0 ? std::max(increment, minimum_increment) : default_increment; 24 | 25 | _increment = effective_increment; 26 | _node = nullptr; 27 | reset(start, capacity); 28 | }; 29 | 30 | util::Heap::~Heap() { reset(nullptr, 0); } 31 | 32 | void *util::Heap::alloc_(size_t size) { 33 | if (_capacity >= size) { 34 | char *result = _free_start; 35 | _free_start += size; 36 | _capacity -= size; 37 | return result; 38 | } 39 | 40 | if (size <= minimum_increment) { 41 | int64_t increment = _increment; 42 | char *buffer = static_cast(malloc(increment)); 43 | 44 | _free_start = buffer; 45 | _capacity = increment; 46 | 47 | Node *node = alloc(); 48 | 49 | node->next = _node; 50 | node->buffer = buffer; 51 | _node = node; 52 | 53 | char *result = _free_start; 54 | _free_start += size; 55 | _capacity -= size; 56 | return result; 57 | } 58 | 59 | Node *node = alloc(); 60 | void *result = malloc(size); 61 | if (result) { 62 | node->next = _node; 63 | node->buffer = result; 64 | _node = node; 65 | } 66 | return result; 67 | } 68 | 69 | void util::Heap::reset(char *_Nullable start, size_t capacity) { 70 | while (_node) { 71 | void *buffer = _node->buffer; 72 | _node = _node->next; 73 | free(buffer); 74 | } 75 | 76 | constexpr uintptr_t alignment_mask = sizeof(char *) - 1; 77 | char *aligned_start = (char *)(((uintptr_t)start + alignment_mask) & ~alignment_mask); 78 | 79 | bool prealigned = ((uintptr_t)start & alignment_mask) == 0; 80 | _free_start = prealigned ? start : aligned_start; 81 | _capacity = capacity + (start - aligned_start); 82 | } 83 | 84 | size_t util::Heap::num_nodes() const { 85 | size_t count = 0; 86 | for (Node *node = _node; node != nullptr; node = node->next) { 87 | count += 1; 88 | } 89 | return count; 90 | } 91 | 92 | void util::Heap::print() const { 93 | fprintf(stdout, "Nodes\n"); 94 | for (Node *node = _node; node != nullptr; node = node->next) { 95 | fprintf(stdout, "address=%-16p; buffer=%-16p; next=%-16p\n", node, node->buffer, node->next); 96 | } 97 | } 98 | 99 | }; /* namespace util */ 100 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Data/zone.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // zone.hpp 3 | // OpenAttributeGraphCxx 4 | 5 | #ifndef zone_hpp 6 | #define zone_hpp 7 | 8 | #include 9 | #include 10 | 11 | namespace OAG { 12 | namespace data { 13 | 14 | class zone { 15 | public: 16 | class info { 17 | public: 18 | OAG_INLINE OAG_CONSTEXPR 19 | info() OAG_NOEXCEPT : _value(0) {}; 20 | 21 | OAG_INLINE OAG_CONSTEXPR 22 | info(uint32_t value) OAG_NOEXCEPT : _value(value){}; 23 | 24 | OAG_INLINE OAG_CONSTEXPR 25 | info(uint32_t zone_id, bool deleted) OAG_NOEXCEPT : _value((zone_id & zone_id_mask) | (deleted ? 1 : 0)) {}; 26 | 27 | OAG_INLINE OAG_CONSTEXPR 28 | uint32_t value() const OAG_NOEXCEPT { return _value; }; 29 | 30 | OAG_INLINE OAG_CONSTEXPR 31 | uint32_t zone_id() const OAG_NOEXCEPT { return _value & zone_id_mask; }; 32 | 33 | OAG_INLINE OAG_CONSTEXPR 34 | bool is_deleted() const OAG_NOEXCEPT { return (_value & deleted) != 0; }; 35 | 36 | OAG_INLINE OAG_CONSTEXPR 37 | info with_zone_id(uint32_t zone_id) const OAG_NOEXCEPT { 38 | return info((_value & ~zone_id_mask) | (zone_id & zone_id_mask), is_deleted()); 39 | }; 40 | 41 | OAG_INLINE OAG_CONSTEXPR 42 | info with_deleted(bool deleted) const OAG_NOEXCEPT { 43 | return info(zone_id(), deleted); 44 | } 45 | private: 46 | enum : uint32_t { 47 | zone_id_mask = 0x7fffffff, 48 | deleted = 0x80000000, 49 | }; 50 | uint32_t _value; 51 | }; /* info */ 52 | public: 53 | // zone() OAG_NOEXCEPT = default; 54 | // ~zone() OAG_NOEXCEPT; 55 | 56 | OAG_INLINE OAG_CONSTEXPR 57 | auto& malloc_buffers() const OAG_NOEXCEPT { return _malloc_buffers; }; 58 | 59 | OAG_INLINE OAG_CONSTEXPR 60 | ptr last_page() const OAG_NOEXCEPT { return _last_page; }; 61 | 62 | OAG_INLINE OAG_CONSTEXPR 63 | info info() const OAG_NOEXCEPT { return _info; }; 64 | 65 | OAG_INLINE 66 | void clear(); 67 | 68 | ptr alloc_slow(uint32_t size, uint32_t alignment_mask) OAG_NOEXCEPT; 69 | 70 | void *alloc_persistent(size_t size) OAG_NOEXCEPT; 71 | 72 | void realloc_bytes(ptr *buffer, uint32_t size, uint32_t new_size, uint32_t alignment_mask) OAG_NOEXCEPT; 73 | 74 | // ptr alloc_bytes(uint32_t size, uint32_t alignment_mask); 75 | ptr alloc_bytes_recycle(uint32_t size, uint32_t alignment_mask) OAG_NOEXCEPT; 76 | 77 | // Printing 78 | void print() const OAG_NOEXCEPT; 79 | 80 | void print_header() const OAG_NOEXCEPT; 81 | private: 82 | typedef struct _bytes_info { 83 | ptr next; 84 | uint32_t size; 85 | } bytes_info; 86 | vector, 0, uint32_t> _malloc_buffers; 87 | ptr _last_page; 88 | ptr _free_bytes; 89 | class info _info; 90 | }; /* zone */ 91 | 92 | } /* data */ 93 | } /* OAG */ 94 | 95 | #endif /* zone_hpp */ 96 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Util/cf_ptr.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // cf_ptr.hpp 3 | // OpenAttributeGraphCxx 4 | // 5 | // Status: Complete 6 | // Modified based Compute code 7 | 8 | #ifndef OPENATTRIBUTEGRAPH_CXX_UTIL_CF_PTR_HPP 9 | #define OPENATTRIBUTEGRAPH_CXX_UTIL_CF_PTR_HPP 10 | 11 | #include 12 | #include 13 | 14 | OAG_ASSUME_NONNULL_BEGIN 15 | 16 | namespace util { 17 | 18 | template class cf_ptr { 19 | private: 20 | CFTypeRef _storage; 21 | 22 | static OAG_INLINE CFTypeRef to_storage(T ref) { return (CFTypeRef)(ref); } 23 | static OAG_INLINE T from_storage(CFTypeRef storage) { return (T)storage; } 24 | 25 | public: 26 | OAG_CONSTEXPR cf_ptr() OAG_NOEXCEPT : _storage(nullptr) {} 27 | OAG_CONSTEXPR cf_ptr(std::nullptr_t) OAG_NOEXCEPT : _storage(nullptr) {} 28 | 29 | explicit cf_ptr(T ref) : _storage(to_storage(ref)) { 30 | if (_storage) { 31 | CFRetain(_storage); 32 | } 33 | } 34 | 35 | ~cf_ptr() { 36 | if (_storage) { 37 | CFRelease(_storage); 38 | } 39 | } 40 | 41 | // Copy and move constructors 42 | 43 | cf_ptr(const cf_ptr &other) OAG_NOEXCEPT : _storage(other._storage) { 44 | if (_storage) { 45 | CFRetain(_storage); 46 | } 47 | }; 48 | 49 | cf_ptr(cf_ptr &&other) OAG_NOEXCEPT : _storage(std::exchange(other._storage, nullptr)) {}; 50 | 51 | // Copy and move assignment operators 52 | 53 | cf_ptr &operator=(const cf_ptr &other) OAG_NOEXCEPT { 54 | if (this != &other) { 55 | if (_storage) { 56 | CFRelease(_storage); 57 | } 58 | _storage = other._storage; 59 | if (_storage) { 60 | CFRetain(_storage); 61 | } 62 | } 63 | return *this; 64 | }; 65 | 66 | cf_ptr &operator=(cf_ptr &&other) OAG_NOEXCEPT { 67 | if (this != &other) { 68 | if (_storage) { 69 | CFRelease(_storage); 70 | } 71 | _storage = other._storage; 72 | other._storage = nullptr; 73 | } 74 | return *this; 75 | } 76 | 77 | // Modifiers 78 | 79 | void reset() OAG_NOEXCEPT { reset(nullptr); } 80 | 81 | void reset(T ref = nullptr) OAG_NOEXCEPT { 82 | if (_storage != ref) { 83 | if (_storage) { 84 | CFRelease(_storage); 85 | } 86 | _storage = to_storage(ref); 87 | if (_storage) { 88 | CFRetain(_storage); 89 | } 90 | } 91 | } 92 | 93 | // Observers 94 | 95 | T get() const OAG_NOEXCEPT { return from_storage(_storage); }; 96 | 97 | explicit operator bool() const OAG_NOEXCEPT { return _storage != nullptr; } 98 | }; /* class cf_ptr */ 99 | 100 | #ifdef SWIFT_TESTING 101 | using cf_data_ptr = cf_ptr; 102 | using cf_mutable_data_ptr = cf_ptr; 103 | #endif /* SWIFT_TESTING */ 104 | 105 | } /* namespace util */ 106 | 107 | OAG_ASSUME_NONNULL_END 108 | 109 | #endif /* OPENATTRIBUTEGRAPH_CXX_UTIL_CF_PTR_HPP */ 110 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Attribute/Attribute/PointerOffset.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PointerOffset.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: Complete 7 | 8 | @frozen 9 | public struct PointerOffset { 10 | public var byteOffset: Int 11 | 12 | public init(byteOffset: Int) { 13 | self.byteOffset = byteOffset 14 | } 15 | } 16 | 17 | extension PointerOffset { 18 | public static func + (_ lhs: PointerOffset, _ rhs: PointerOffset) -> PointerOffset { 19 | PointerOffset(byteOffset: lhs.byteOffset + rhs.byteOffset) 20 | } 21 | } 22 | 23 | extension PointerOffset { 24 | public static func invalidScenePointer() -> UnsafeMutablePointer { 25 | #if OPENATTRIBUTEGRAPH_RELEASE_2024 26 | UnsafeMutablePointer(bitPattern: 0x1)! 27 | #else 28 | UnsafeMutablePointer(bitPattern: MemoryLayout.stride)! 29 | #endif 30 | } 31 | 32 | public static func of(_ member: inout Member) -> PointerOffset { 33 | withUnsafePointer(to: &member) { memberPointer in 34 | let offset = UnsafeRawPointer(memberPointer) - UnsafeRawPointer(invalidScenePointer()) 35 | return PointerOffset(byteOffset: offset) 36 | } 37 | } 38 | 39 | public static func offset(_ body: (inout Base) -> PointerOffset) -> PointerOffset { 40 | guard MemoryLayout.size != 0 else { 41 | return PointerOffset(byteOffset: 0) 42 | } 43 | return body(&invalidScenePointer().pointee) 44 | } 45 | } 46 | 47 | extension PointerOffset where Base == Member { 48 | public init() { byteOffset = 0 } 49 | } 50 | 51 | extension UnsafePointer { 52 | public subscript(offset offset: PointerOffset) -> Member { 53 | unsafeAddress { 54 | UnsafeRawPointer(self) 55 | .advanced(by: offset.byteOffset) 56 | .assumingMemoryBound(to: Member.self) 57 | } 58 | } 59 | 60 | public static func + ( 61 | _ lhs: UnsafePointer, 62 | _ rhs: PointerOffset 63 | ) -> UnsafePointer { 64 | UnsafeRawPointer(lhs) 65 | .advanced(by: rhs.byteOffset) 66 | .assumingMemoryBound(to: Member.self) 67 | } 68 | } 69 | 70 | extension UnsafeMutablePointer { 71 | public subscript(offset offset: PointerOffset) -> Member { 72 | unsafeAddress { 73 | UnsafeRawPointer(self) 74 | .advanced(by: offset.byteOffset) 75 | .assumingMemoryBound(to: Member.self) 76 | } 77 | 78 | nonmutating unsafeMutableAddress { 79 | UnsafeMutableRawPointer(self) 80 | .advanced(by: offset.byteOffset) 81 | .assumingMemoryBound(to: Member.self) 82 | } 83 | } 84 | 85 | public static func + ( 86 | _ lhs: UnsafeMutablePointer, 87 | _ rhs: PointerOffset 88 | ) -> UnsafeMutablePointer { 89 | UnsafeMutableRawPointer(lhs) 90 | .advanced(by: rhs.byteOffset) 91 | .assumingMemoryBound(to: Member.self) 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Attribute/Attribute/AnyAttribute.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnyAttribute.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: API complete 7 | 8 | public import OpenAttributeGraphCxx 9 | 10 | @_silgen_name("OAGGraphMutateAttribute") 11 | private func OAGGraphMutateAttribute( 12 | _ attribute: AnyAttribute, 13 | type: Metadata, 14 | invalidating: Bool, 15 | body: (UnsafeMutableRawPointer) -> Void 16 | ) 17 | 18 | extension AnyAttribute { 19 | public init(_ attribute: Attribute) { 20 | self = attribute.identifier 21 | } 22 | 23 | public func unsafeCast(to _: Value.Type) -> Attribute { 24 | Attribute(identifier: self) 25 | } 26 | 27 | public static var current: AnyAttribute? { 28 | let current = __OAGGraphGetCurrentAttribute() 29 | return current == .nil ? nil : current 30 | } 31 | 32 | public func unsafeOffset(at offset: Int) -> AnyAttribute { 33 | create(offset: offset) 34 | } 35 | 36 | public func setFlags(_ newFlags: Flags, mask: Flags) { 37 | flags = flags.subtracting(mask).union(newFlags.intersection(mask)) 38 | } 39 | 40 | public func addInput(_ attribute: AnyAttribute, options: OAGInputOptions = [], token: Int) { 41 | __OAGGraphAddInput(self, attribute, options, token) 42 | } 43 | 44 | public func addInput(_ attribute: Attribute, options: OAGInputOptions = [], token: Int) { 45 | addInput(attribute.identifier, options: options, token: token) 46 | } 47 | 48 | // FIXME: Use AttributeType instead 49 | public func visitBody(_ visitor: inout Body) { 50 | let bodyType = info.type.advanced(by: 1).pointee.self_id.type as! _AttributeBody.Type 51 | bodyType._visitBody(&visitor, info.body) 52 | } 53 | 54 | public func mutateBody(as type: Value.Type, invalidating: Bool, _ body: (inout Value) -> Void) { 55 | OAGGraphMutateAttribute( 56 | self, 57 | type: Metadata(type), 58 | invalidating: invalidating 59 | ) { value in 60 | body(&value.assumingMemoryBound(to: Value.self).pointee) 61 | } 62 | } 63 | 64 | public func breadthFirstSearch(options _: SearchOptions = [], _: (AnyAttribute) -> Bool) -> Bool { 65 | fatalError("TODO") 66 | } 67 | 68 | public var _bodyType: Any.Type { 69 | info.type.pointee.self_id.type 70 | } 71 | 72 | public var _bodyPointer: UnsafeRawPointer { 73 | info.body 74 | } 75 | 76 | public var valueType: Any.Type { 77 | info.type.pointee.value_id.type 78 | } 79 | 80 | public var indirectDependency: AnyAttribute? { 81 | get { 82 | let indirectDependency = _indirectDependency 83 | return indirectDependency == .nil ? nil : indirectDependency 84 | } 85 | nonmutating set { 86 | _indirectDependency = newValue ?? .nil 87 | } 88 | } 89 | } 90 | 91 | // MARK: CustomStringConvertible 92 | 93 | extension AnyAttribute: Swift.CustomStringConvertible { 94 | @inlinable 95 | public var description: String { "#\(rawValue)" } 96 | } 97 | 98 | public typealias AttributeUpdateBlock = () -> (UnsafeMutableRawPointer, AnyAttribute) -> Void 99 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraph/Attribute/RuleContext/RuleContext.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RuleContext.swift 3 | // OpenAttributeGraph 4 | // 5 | // Audited for RELEASE_2021 6 | // Status: Complete 7 | 8 | public import OpenAttributeGraphCxx 9 | 10 | /// Context object providing access to rule evaluation state and input values. 11 | @frozen 12 | public struct RuleContext: Equatable { 13 | public var attribute: Attribute 14 | 15 | public init(attribute: Attribute) { 16 | self.attribute = attribute 17 | } 18 | 19 | public subscript(attribute: Attribute) -> V { 20 | unsafeAddress { 21 | OAGGraphGetInputValue(self.attribute.identifier, input: attribute.identifier, type: V.self) 22 | .value 23 | .assumingMemoryBound(to: V.self) 24 | } 25 | } 26 | 27 | public subscript(weakAttribute: WeakAttribute) -> V? { 28 | weakAttribute.attribute.map { attribute in 29 | OAGGraphGetInputValue(self.attribute.identifier, input: attribute.identifier, type: V.self) 30 | .value 31 | .assumingMemoryBound(to: V.self) 32 | .pointee 33 | } 34 | } 35 | 36 | public subscript(optionalAttribute: OptionalAttribute) -> V? { 37 | optionalAttribute.attribute.map { attribute in 38 | OAGGraphGetInputValue(self.attribute.identifier, input: attribute.identifier, type: V.self) 39 | .value 40 | .assumingMemoryBound(to: V.self) 41 | .pointee 42 | } 43 | } 44 | 45 | public var value: Value { 46 | unsafeAddress { 47 | Graph.outputValue()! 48 | } 49 | nonmutating set { 50 | withUnsafePointer(to: newValue) { value in 51 | Graph.setOutputValue(value) 52 | } 53 | } 54 | } 55 | 56 | public var hasValue: Bool { 57 | let valuePointer: UnsafePointer? = Graph.outputValue() 58 | return valuePointer != nil 59 | } 60 | 61 | public func valueAndFlags(of input: Attribute, options: OAGValueOptions = []) -> (value: V, flags: OAGChangedValueFlags) { 62 | let value = OAGGraphGetInputValue(attribute.identifier, input: input.identifier, options: options, type: V.self) 63 | return ( 64 | value.value.assumingMemoryBound(to: V.self).pointee, 65 | value.flags 66 | ) 67 | } 68 | 69 | public func changedValue(of input: Attribute, options: OAGValueOptions = []) -> (value: V, changed: Bool) { 70 | let value = OAGGraphGetInputValue(attribute.identifier, input: input.identifier, options: options, type: V.self) 71 | return ( 72 | value.value.assumingMemoryBound(to: V.self).pointee, 73 | value.flags.contains(.changed) 74 | ) 75 | } 76 | 77 | public func update(body: () -> Void) { 78 | OAGGraphWithUpdate(attribute.identifier, body: body) 79 | } 80 | } 81 | 82 | @_silgen_name("OAGGraphGetInputValue") 83 | @inline(__always) 84 | @inlinable 85 | func OAGGraphGetInputValue(_ attribute: AnyAttribute, input: AnyAttribute, options: OAGValueOptions = [], type: Value.Type = Value.self) -> OAGValue 86 | 87 | @_silgen_name("OAGGraphWithUpdate") 88 | @inline(__always) 89 | @inlinable 90 | func OAGGraphWithUpdate(_ attribute: AnyAttribute, body: () -> Void) 91 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Util/objc_ptr.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // objc_ptr.hpp 3 | // OpenAttributeGraphCxx 4 | // 5 | // Status: Complete 6 | // Modified based Compute code 7 | 8 | #ifndef OPENATTRIBUTEGRAPH_CXX_UTIL_OBJC_PTR_HPP 9 | #define OPENATTRIBUTEGRAPH_CXX_UTIL_OBJC_PTR_HPP 10 | 11 | #include 12 | 13 | #if OAG_TARGET_OS_DARWIN 14 | #include 15 | #include 16 | 17 | OAG_ASSUME_NONNULL_BEGIN 18 | 19 | // Redeclare APIs from the Objective-C runtime. 20 | // These functions are not available through public headers, but are guaranteed 21 | // to exist on OS X >= 10.9 and iOS >= 7.0. 22 | OBJC_EXPORT id objc_retain(id obj); 23 | OBJC_EXPORT void objc_release(id obj); 24 | 25 | namespace util { 26 | 27 | template class objc_ptr { 28 | private: 29 | id _storage; 30 | 31 | static OAG_INLINE id to_storage(T obj) { return (id)obj; } 32 | static OAG_INLINE T from_storage(id storage) { return (T)storage; } 33 | 34 | public: 35 | OAG_CONSTEXPR objc_ptr() OAG_NOEXCEPT : _storage(nil) {} 36 | OAG_CONSTEXPR objc_ptr(std::nullptr_t) OAG_NOEXCEPT : _storage(nil) {} 37 | 38 | explicit objc_ptr(T obj) : _storage(to_storage(obj)) { 39 | if (_storage) { 40 | objc_retain(_storage); 41 | } 42 | } 43 | 44 | ~objc_ptr() { 45 | if (_storage) { 46 | objc_release(_storage); 47 | } 48 | } 49 | 50 | // MARK: - Copy and move constructors 51 | 52 | objc_ptr(const objc_ptr &other) OAG_NOEXCEPT : _storage(other._storage) { 53 | if (_storage) { 54 | objc_retain(_storage); 55 | } 56 | } 57 | 58 | objc_ptr(objc_ptr &&other) OAG_NOEXCEPT : _storage(other._storage) { 59 | other._storage = nil; 60 | } 61 | 62 | // MARK: - Copy and move assignment operators 63 | 64 | objc_ptr &operator=(const objc_ptr &other) OAG_NOEXCEPT { 65 | if (this != &other) { 66 | if (_storage) { 67 | objc_release(_storage); 68 | } 69 | _storage = other._storage; 70 | if (_storage) { 71 | objc_retain(_storage); 72 | } 73 | } 74 | return *this; 75 | } 76 | 77 | objc_ptr &operator=(objc_ptr &&other) OAG_NOEXCEPT { 78 | if (this != &other) { 79 | if (_storage) { 80 | objc_release(_storage); 81 | } 82 | _storage = other._storage; 83 | other._storage = nil; 84 | } 85 | return *this; 86 | } 87 | 88 | // MARK: - Modifiers 89 | 90 | void reset() OAG_NOEXCEPT { reset(nil); } 91 | 92 | void reset(T obj = nil) OAG_NOEXCEPT { 93 | if (_storage != obj) { 94 | if (_storage) { 95 | objc_release(_storage); 96 | } 97 | _storage = to_storage(obj); 98 | if (_storage) { 99 | objc_retain(_storage); 100 | } 101 | } 102 | } 103 | 104 | T get() const OAG_NOEXCEPT { return from_storage(_storage); } 105 | 106 | explicit operator bool() const OAG_NOEXCEPT { return _storage != nil; } 107 | }; /* class objc_ptr */ 108 | 109 | } /* namespace util */ 110 | 111 | OAG_ASSUME_NONNULL_END 112 | 113 | #endif 114 | 115 | #endif /* OPENATTRIBUTEGRAPH_CXX_UTIL_OBJC_PTR_HPP */ 116 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGTupleType.h: -------------------------------------------------------------------------------- 1 | // 2 | // OAGTupleType.h 3 | // OpenAttributeGraphCxx 4 | // 5 | // Audited for iOS 18.0 6 | // Status: Complete 7 | 8 | #ifndef OAGTupleType_h 9 | #define OAGTupleType_h 10 | 11 | #include 12 | #include 13 | 14 | OAG_ASSUME_NONNULL_BEGIN 15 | 16 | OAG_IMPLICIT_BRIDGING_ENABLED 17 | 18 | typedef const OAGSwiftMetadata *OAGTupleType OAG_SWIFT_STRUCT OAG_SWIFT_NAME(TupleType); 19 | 20 | typedef OAG_CLOSED_ENUM(uint32_t, OAGTupleCopyOptions) { 21 | OAGTupleCopyOptionsAssignCopy = 0, 22 | OAGTupleCopyOptionsInitCopy = 1, 23 | OAGTupleCopyOptionsAssignTake = 2, 24 | OAGTupleCopyOptionsInitTake = 3 25 | } OAG_SWIFT_NAME(TupleType.CopyOptions); 26 | 27 | typedef struct OAG_SWIFT_NAME(UnsafeTuple) OAGUnsafeTuple { 28 | OAGTupleType type; 29 | const void *value; 30 | } OAGUnsafeTuple; 31 | 32 | typedef struct OAG_SWIFT_NAME(UnsafeMutableTuple) OAGUnsafeMutableTuple { 33 | OAGTupleType type; 34 | void *value; 35 | } OAGUnsafeMutableTuple; 36 | 37 | OAG_EXTERN_C_BEGIN 38 | 39 | OAG_EXPORT 40 | OAG_REFINED_FOR_SWIFT 41 | OAGTupleType OAGNewTupleType(size_t count, const OAGTypeID _Nonnull * _Nonnull elements) OAG_SWIFT_NAME(TupleType.init(count:elements:)); 42 | 43 | OAG_EXPORT 44 | OAG_REFINED_FOR_SWIFT 45 | size_t OAGTupleCount(OAGTupleType tuple_type) OAG_SWIFT_NAME(getter:TupleType.count(self:)); 46 | 47 | OAG_EXPORT 48 | OAG_REFINED_FOR_SWIFT 49 | size_t OAGTupleSize(OAGTupleType tuple_type) OAG_SWIFT_NAME(getter:TupleType.size(self:)); 50 | 51 | OAG_EXPORT 52 | OAG_REFINED_FOR_SWIFT 53 | OAGTypeID OAGTupleElementType(OAGTupleType tuple_type, size_t index) OAG_SWIFT_NAME(TupleType.elementType(self:at:)); 54 | 55 | OAG_EXPORT 56 | OAG_REFINED_FOR_SWIFT 57 | size_t OAGTupleElementSize(OAGTupleType tuple_type, size_t index) OAG_SWIFT_NAME(TupleType.elementSize(self:at:)); 58 | 59 | OAG_EXPORT 60 | OAG_REFINED_FOR_SWIFT 61 | size_t OAGTupleElementOffset(OAGTupleType tuple_type, size_t index) OAG_SWIFT_NAME(TupleType.elementOffset(self:at:)); 62 | 63 | OAG_EXPORT 64 | OAG_REFINED_FOR_SWIFT 65 | size_t OAGTupleElementOffsetChecked(OAGTupleType tuple_type, size_t index, OAGTypeID check_type) OAG_SWIFT_NAME(TupleType.elementOffset(self:at:type:)); 66 | 67 | OAG_EXPORT 68 | OAG_REFINED_FOR_SWIFT 69 | void *OAGTupleSetElement(OAGTupleType tuple_type, void* tuple_value, size_t index, const void *element_value, OAGTypeID check_type, OAGTupleCopyOptions mode); 70 | 71 | OAG_EXPORT 72 | OAG_REFINED_FOR_SWIFT 73 | void *OAGTupleGetElement(OAGTupleType tuple_type, void* tuple_value, size_t index, void *element_value, OAGTypeID check_type, OAGTupleCopyOptions mode); 74 | 75 | OAG_EXPORT 76 | OAG_REFINED_FOR_SWIFT 77 | void OAGTupleDestroy(OAGTupleType tuple_type, void *buffer) OAG_SWIFT_NAME(TupleType.destroy(self:_:)); 78 | 79 | OAG_EXPORT 80 | OAG_REFINED_FOR_SWIFT 81 | void OAGTupleDestroyElement(OAGTupleType tuple_type, void *buffer, size_t index) OAG_SWIFT_NAME(TupleType.destroy(self:_:at:)); 82 | 83 | OAG_EXPORT 84 | OAG_REFINED_FOR_SWIFT 85 | void OAGTupleWithBuffer(OAGTupleType tuple_type, size_t count, const void (* function)(const OAGUnsafeMutableTuple mutableTuple, const void * context OAG_SWIFT_CONTEXT) OAG_SWIFT_CC(swift), const void *context); 86 | 87 | OAG_EXTERN_C_END 88 | 89 | OAG_IMPLICIT_BRIDGING_DISABLED 90 | 91 | OAG_ASSUME_NONNULL_END 92 | 93 | #endif /* OAGTupleType_h */ 94 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphShims/Attribute+Debug.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Attribute+Debug.swift 3 | // OpenAttributeGraphShims 4 | 5 | #if canImport(Darwin) && DEBUG // Compiler crash for Darwin + release and non-Darwin build 6 | 7 | // Use 4 spaces instead of \t for bettern test case expect 8 | private let tab = " " 9 | 10 | extension Attribute: Swift.CustomDebugStringConvertible { 11 | public var debugDescription: String { 12 | _debugDescription(indent: 0) 13 | } 14 | 15 | func _debugDescription(indent: Int) -> String { 16 | let tabs = String(repeating: tab, count: indent) 17 | return #""" 18 | \#(tabs)Attribute<\#(Value.self)> { 19 | \#(identifier._debugDescription(indent: indent + 1)) 20 | \#(tabs)} 21 | """# 22 | } 23 | } 24 | 25 | extension AnyAttribute: Swift.CustomDebugStringConvertible { 26 | public var debugDescription: String { 27 | _debugDescription(indent: 0) 28 | } 29 | 30 | func _debugDescription(indent: Int) -> String { 31 | let tabs = String(repeating: tab, count: indent) 32 | 33 | guard self != .nil else { 34 | return "\(tabs)AnyAttribute.nil" 35 | } 36 | 37 | var description = #""" 38 | \#(tabs)rawValue: \#(rawValue) 39 | \#(tabs)graph: \#(graph) 40 | """# 41 | 42 | if rawValue % 2 == 0 { // direct 43 | description.append("\n\(tabs)(direct attribute)") 44 | 45 | let valueType = valueType 46 | description.append("\n\(tabs)valueType: \(valueType)") 47 | 48 | var value: Any! 49 | func project1(type: T.Type) { 50 | value = unsafeCast(to: type).value 51 | } 52 | _openExistential(valueType, do: project1) 53 | description.append("\n\(tabs)value: \(value!)") 54 | 55 | let bodyType = _bodyType 56 | description.append("\n\(tabs)bodyType: \(bodyType)") 57 | 58 | var bodyValue: Any! 59 | func project2(type: T.Type) { 60 | bodyValue = _bodyPointer.assumingMemoryBound(to: type).pointee 61 | } 62 | _openExistential(bodyType, do: project2) 63 | 64 | let bodyValueDescription = _formatBodyValue(bodyValue!, indent: indent) 65 | description.append("\n\(tabs)bodyValue:\n\(bodyValueDescription)") 66 | 67 | } else { // indirect 68 | description.append("\n\(tabs)(indirect attribute)") 69 | description.append("\n\(tabs)source attribute:") 70 | description.append("\n\(source._debugDescription(indent: indent + 1))") 71 | } 72 | return description 73 | } 74 | 75 | private func _formatBodyValue(_ bodyValue: Any, indent: Int) -> String { 76 | let bodyValueString = String(describing: bodyValue) 77 | let nextTabs = String(repeating: tab, count: indent + 1) 78 | 79 | // Check if the body value contains attributes 80 | if bodyValueString.contains("Attribute<") { 81 | // Split lines and add proper indentation 82 | let lines = bodyValueString.components(separatedBy: .newlines) 83 | return lines.enumerated().map { index, line in 84 | return "\(nextTabs)\(line)" 85 | }.joined(separator: "\n") 86 | } 87 | 88 | return "\(nextTabs)\(bodyValueString)" 89 | } 90 | } 91 | #endif 92 | -------------------------------------------------------------------------------- /Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Data/ptr.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // ptr.hpp 3 | // OpenAttributeGraphCxx 4 | // 5 | // Status: Complete 6 | // Modified based Compute code 7 | 8 | #ifndef ptr_hpp 9 | #define ptr_hpp 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | OAG_ASSUME_NONNULL_BEGIN 17 | 18 | namespace OAG { 19 | namespace data { 20 | 21 | struct page; 22 | 23 | template class ptr { 24 | public: 25 | using element_type = T; 26 | using difference_type = uint32_t; 27 | 28 | public: 29 | OAG_INLINE OAG_CONSTEXPR ptr(difference_type offset = 0) : _offset(offset){}; 30 | OAG_INLINE OAG_CONSTEXPR ptr(std::nullptr_t){}; 31 | 32 | // FIXME: this should be put into table API 33 | OAG_INLINE 34 | element_type *_Nonnull get(vm_address_t base = shared_table().data_base()) const OAG_NOEXCEPT { 35 | assert(_offset != 0); 36 | return reinterpret_cast(base + _offset); 37 | } 38 | 39 | OAG_INLINE OAG_CONSTEXPR 40 | ptr page_ptr() const OAG_NOEXCEPT { return ptr(_offset & page_alignment); } 41 | 42 | OAG_INLINE OAG_CONSTEXPR 43 | uint32_t page_index() const OAG_NOEXCEPT { return (_offset >> page_mask_bits) - 1; } 44 | 45 | OAG_INLINE OAG_CONSTEXPR 46 | difference_type page_relative_offset() const OAG_NOEXCEPT { return _offset & page_mask; } 47 | 48 | template ptr aligned(difference_type alignment_mask = sizeof(difference_type) - 1) const { 49 | return ptr((_offset + alignment_mask) & ~alignment_mask); 50 | }; 51 | 52 | OAG_INLINE OAG_CONSTEXPR 53 | operator bool() const OAG_NOEXCEPT { return _offset != 0; }; 54 | 55 | OAG_INLINE OAG_CONSTEXPR 56 | std::add_lvalue_reference_t operator*() const OAG_NOEXCEPT { return *get(); }; 57 | 58 | OAG_INLINE OAG_CONSTEXPR 59 | T *_Nonnull operator->() const OAG_NOEXCEPT { return get(); }; 60 | 61 | OAG_INLINE OAG_CONSTEXPR 62 | bool operator==(std::nullptr_t) const OAG_NOEXCEPT { return _offset == 0; }; 63 | 64 | OAG_INLINE OAG_CONSTEXPR 65 | bool operator!=(std::nullptr_t) const OAG_NOEXCEPT { return _offset != 0; }; 66 | 67 | OAG_INLINE OAG_CONSTEXPR 68 | bool operator<(difference_type offset) const OAG_NOEXCEPT { return _offset < offset; }; 69 | 70 | OAG_INLINE OAG_CONSTEXPR 71 | bool operator<=(difference_type offset) const OAG_NOEXCEPT { return _offset <= offset; }; 72 | 73 | OAG_INLINE OAG_CONSTEXPR 74 | bool operator>(difference_type offset) const OAG_NOEXCEPT { return _offset > offset; }; 75 | 76 | OAG_INLINE OAG_CONSTEXPR 77 | bool operator>=(difference_type offset) const OAG_NOEXCEPT { return _offset >= offset; }; 78 | 79 | template 80 | OAG_INLINE OAG_CONSTEXPR 81 | ptr operator+(difference_type shift) const OAG_NOEXCEPT { return ptr(_offset + shift); }; 82 | 83 | template 84 | OAG_INLINE OAG_CONSTEXPR 85 | ptr operator-(difference_type shift) const OAG_NOEXCEPT { return ptr(_offset - shift); }; 86 | 87 | template 88 | OAG_INLINE OAG_CONSTEXPR 89 | difference_type operator-(const ptr &other) const OAG_NOEXCEPT { 90 | return _offset - other._offset; 91 | }; 92 | private: 93 | difference_type _offset; 94 | 95 | template friend class ptr; 96 | friend class table; 97 | }; /* ptr */ 98 | 99 | } /* data */ 100 | } /* OAG */ 101 | 102 | OAG_ASSUME_NONNULL_END 103 | 104 | #endif /* ptr_hpp */ 105 | --------------------------------------------------------------------------------