Skip to content

Commit c7b3870

Browse files
authored
Add Swift Reflection Package (swiftlang#62819)
1 parent 2adb84d commit c7b3870

File tree

70 files changed

+7208
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+7208
-0
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// swift-tools-version: 5.7
2+
3+
import PackageDescription
4+
5+
let package = Package(
6+
name: "Reflection",
7+
platforms: [
8+
.macOS(.v13)
9+
],
10+
products: [
11+
.library(
12+
name: "Runtime",
13+
type: .dynamic,
14+
targets: ["Runtime"]
15+
),
16+
.library(
17+
name: "Reflection",
18+
type: .dynamic,
19+
targets: ["Reflection"]
20+
),
21+
],
22+
targets: [
23+
.target(
24+
name: "CRuntime"
25+
),
26+
.target(
27+
name: "Runtime",
28+
dependencies: ["CRuntime"],
29+
swiftSettings: [
30+
.unsafeFlags([
31+
"-parse-stdlib",
32+
"-enable-library-evolution",
33+
"-Xfrontend", "-disable-implicit-concurrency-module-import",
34+
"-Xfrontend", "-disable-implicit-string-processing-module-import",
35+
"-assert-config", "Release"
36+
])
37+
]
38+
),
39+
.target(
40+
name: "Reflection",
41+
dependencies: ["Runtime"],
42+
swiftSettings: [
43+
.unsafeFlags([
44+
"-parse-stdlib",
45+
"-enable-library-evolution",
46+
"-Xfrontend", "-disable-implicit-concurrency-module-import",
47+
"-Xfrontend", "-disable-implicit-string-processing-module-import",
48+
"-assert-config", "Release"
49+
])
50+
]
51+
),
52+
53+
.testTarget(
54+
name: "RuntimeTests",
55+
dependencies: ["Runtime"]
56+
),
57+
.testTarget(
58+
name: "ReflectionTests",
59+
dependencies: ["Runtime", "Reflection"]
60+
),
61+
]
62+
)

stdlib/public/Reflection/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Reflection
2+
3+
A description of this package.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
#include "include/Functions.h"
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
#ifndef FUNCTIONS_H
13+
#define FUNCTIONS_H
14+
15+
// OpaqueValue *swift_projectBox(HeapObject *object);
16+
extern void *swift_projectBox(void *object);
17+
18+
// WitnessTable *swift_conformsToProtocol(Metadata *type,
19+
// ProtocolDescriptor *protocol);
20+
extern void *swift_conformsToProtocol(const void *type, const void *protocol);
21+
22+
#endif /* FUNCTIONS_H */
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
import Swift
13+
import Runtime
14+
15+
@frozen
16+
public struct Case {
17+
@usableFromInline
18+
let parent: EnumMetadata
19+
20+
@usableFromInline
21+
let tag: Int
22+
23+
@inlinable
24+
init(parent: EnumMetadata, tag: Int) {
25+
self.parent = parent
26+
self.tag = tag
27+
}
28+
29+
@inlinable
30+
public init?(from instance: Any) {
31+
guard Type(instance).isEnum else {
32+
return nil
33+
}
34+
35+
var container = unsafeBitCast(instance, to: AnyExistentialContainer.self)
36+
37+
let tag = container.projectValue {
38+
Metadata(type(of: instance)).enum.enumVWT.getEnumTag($0)
39+
}
40+
41+
self.parent = Metadata(type(of: instance)).enum
42+
self.tag = Int(truncatingIfNeeded: tag)
43+
}
44+
}
45+
46+
extension Case {
47+
@inlinable
48+
public var hasPayload: Bool {
49+
tag < parent.descriptor.numberOfPayloadCases
50+
}
51+
52+
@inlinable
53+
public var isIndirect: Bool {
54+
parent.descriptor.type.fields[tag].flags.isIndirectCase
55+
}
56+
57+
@inlinable
58+
public var name: String {
59+
parent.descriptor.type.fields[tag].name
60+
}
61+
62+
@inlinable
63+
public var payloadType: Type? {
64+
guard tag < parent.descriptor.numberOfPayloadCases else {
65+
return nil
66+
}
67+
68+
let typeRef = parent.descriptor.type.fields[tag].typeRef
69+
70+
guard let resolved = parent.type.resolve(typeRef) else {
71+
return nil
72+
}
73+
74+
return Type(resolved)
75+
}
76+
}
77+
78+
extension Case: CustomStringConvertible {
79+
@inlinable
80+
public var description: String {
81+
var result = "\(unsafeBitCast(parent, to: Any.Type.self)).\(name)"
82+
83+
if hasPayload {
84+
let ty = payloadType!
85+
86+
if ty.isTuple {
87+
result += "\(ty)"
88+
} else {
89+
result += "(\(ty))"
90+
}
91+
}
92+
93+
return result
94+
}
95+
}
96+
97+
@frozen
98+
public struct Cases {
99+
@usableFromInline
100+
let metadata: Metadata
101+
102+
@inlinable
103+
init(_ metadata: Metadata) {
104+
self.metadata = metadata
105+
}
106+
}
107+
108+
extension Cases: RandomAccessCollection {
109+
@inlinable
110+
public var startIndex: Int {
111+
0
112+
}
113+
114+
@inlinable
115+
public var endIndex: Int {
116+
guard Type(metadata).isEnum else {
117+
return 0
118+
}
119+
120+
return metadata.enum.descriptor.numberOfCases
121+
}
122+
123+
@inlinable
124+
public func index(after i: Int) -> Int {
125+
i + 1
126+
}
127+
128+
@inlinable
129+
public func index(before i: Int) -> Int {
130+
i - 1
131+
}
132+
133+
@inlinable
134+
public subscript(_ position: Int) -> Case {
135+
precondition(position < endIndex)
136+
137+
return Case(parent: metadata.enum, tag: position)
138+
}
139+
}
140+
141+
extension Type {
142+
@inlinable
143+
public var cases: Cases {
144+
Cases(metadata)
145+
}
146+
}

0 commit comments

Comments
 (0)