Skip to content

Commit 7969272

Browse files
authored
Merge pull request #376 from Azoy/types-types-and-more-types
Implement .as for Regex and Unify Match and AnyRegexOutput
2 parents ba33c0d + c7b70a4 commit 7969272

File tree

9 files changed

+247
-187
lines changed

9 files changed

+247
-187
lines changed

Sources/_RegexParser/Utility/TypeConstruction.swift

Lines changed: 42 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,7 @@
1717
// const Metadata * const *elements,
1818
// const char *labels,
1919
// const ValueWitnessTable *proposedWitnesses);
20-
//
21-
// SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
22-
// MetadataResponse
23-
// swift_getTupleTypeMetadata2(MetadataRequest request,
24-
// const Metadata *elt0, const Metadata *elt1,
25-
// const char *labels,
26-
// const ValueWitnessTable *proposedWitnesses);
27-
// SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
28-
// MetadataResponse
29-
// swift_getTupleTypeMetadata3(MetadataRequest request,
30-
// const Metadata *elt0, const Metadata *elt1,
31-
// const Metadata *elt2, const char *labels,
32-
// const ValueWitnessTable *proposedWitnesses);
20+
3321

3422
@_silgen_name("swift_getTupleTypeMetadata")
3523
private func swift_getTupleTypeMetadata(
@@ -40,31 +28,13 @@ private func swift_getTupleTypeMetadata(
4028
proposedWitnesses: UnsafeRawPointer?
4129
) -> (value: Any.Type, state: Int)
4230

43-
@_silgen_name("swift_getTupleTypeMetadata2")
44-
private func swift_getTupleTypeMetadata2(
45-
request: Int,
46-
element1: Any.Type,
47-
element2: Any.Type,
48-
labels: UnsafePointer<Int8>?,
49-
proposedWitnesses: UnsafeRawPointer?
50-
) -> (value: Any.Type, state: Int)
51-
52-
@_silgen_name("swift_getTupleTypeMetadata3")
53-
private func swift_getTupleTypeMetadata3(
54-
request: Int,
55-
element1: Any.Type,
56-
element2: Any.Type,
57-
element3: Any.Type,
58-
labels: UnsafePointer<Int8>?,
59-
proposedWitnesses: UnsafeRawPointer?
60-
) -> (value: Any.Type, state: Int)
61-
6231
public enum TypeConstruction {
6332
/// Returns a tuple metatype of the given element types.
6433
public static func tupleType<
6534
ElementTypes: BidirectionalCollection
6635
>(
67-
of elementTypes: __owned ElementTypes
36+
of elementTypes: __owned ElementTypes,
37+
labels: String? = nil
6838
) -> Any.Type where ElementTypes.Element == Any.Type {
6939
// From swift/ABI/Metadata.h:
7040
// template <typename int_type>
@@ -78,39 +48,50 @@ public enum TypeConstruction {
7848
let elementCountFlag = 0x0000FFFF
7949
assert(elementTypes.count != 1, "A one-element tuple is not a realistic Swift type")
8050
assert(elementTypes.count <= elementCountFlag, "Tuple size exceeded \(elementCountFlag)")
81-
switch elementTypes.count {
82-
case 2:
83-
return swift_getTupleTypeMetadata2(
84-
request: 0,
85-
element1: elementTypes[elementTypes.startIndex],
86-
element2: elementTypes[elementTypes.index(elementTypes.startIndex, offsetBy: 1)],
87-
labels: nil,
88-
proposedWitnesses: nil).value
89-
case 3:
90-
return swift_getTupleTypeMetadata3(
91-
request: 0,
92-
element1: elementTypes[elementTypes.startIndex],
93-
element2: elementTypes[elementTypes.index(elementTypes.startIndex, offsetBy: 1)],
94-
element3: elementTypes[elementTypes.index(elementTypes.startIndex, offsetBy: 2)],
95-
labels: nil,
96-
proposedWitnesses: nil).value
97-
default:
98-
let result = elementTypes.withContiguousStorageIfAvailable { elementTypesBuffer in
99-
swift_getTupleTypeMetadata(
51+
52+
var flags = elementTypes.count
53+
54+
// If we have labels to provide, then say the label pointer is not constant
55+
// because the lifetime of said pointer will only be vaild for the lifetime
56+
// of the 'swift_getTupleTypeMetadata' call. If we don't have labels, then
57+
// our label pointer will be empty and constant.
58+
if labels != nil {
59+
// Has non constant labels
60+
flags |= 0x10000
61+
}
62+
63+
let result = elementTypes.withContiguousStorageIfAvailable { elementTypesBuffer in
64+
if let labels = labels {
65+
return labels.withCString { labelsPtr in
66+
swift_getTupleTypeMetadata(
67+
request: 0,
68+
flags: flags,
69+
elements: elementTypesBuffer.baseAddress,
70+
labels: labelsPtr,
71+
proposedWitnesses: nil
72+
)
73+
}
74+
} else {
75+
return swift_getTupleTypeMetadata(
10076
request: 0,
101-
flags: elementTypesBuffer.count,
77+
flags: flags,
10278
elements: elementTypesBuffer.baseAddress,
10379
labels: nil,
104-
proposedWitnesses: nil).value
80+
proposedWitnesses: nil
81+
)
10582
}
106-
guard let result = result else {
107-
fatalError("""
108-
The collection of element types does not support an internal representation of
109-
contiguous storage
110-
""")
111-
}
112-
return result
11383
}
84+
85+
guard let result = result else {
86+
fatalError(
87+
"""
88+
The collection of element types does not support an internal representation of
89+
contiguous storage
90+
"""
91+
)
92+
}
93+
94+
return result.value
11495
}
11596

11697
/// Creates a type-erased tuple with the given elements.

Sources/_StringProcessing/Capture.swift

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,6 @@
1111

1212
@_implementationOnly import _RegexParser
1313

14-
/// A structured capture
15-
struct StructuredCapture {
16-
/// The `.optional` height of the result
17-
var optionalCount = 0
18-
19-
var storedCapture: StoredCapture?
20-
21-
var someCount: Int {
22-
storedCapture == nil ? optionalCount - 1 : optionalCount
23-
}
24-
}
25-
26-
/// A storage form for a successful capture
27-
struct StoredCapture {
28-
// TODO: drop optional when engine tracks all ranges
29-
var range: Range<String.Index>?
30-
31-
// If strongly typed, value is set
32-
var value: Any? = nil
33-
}
34-
3514
// TODO: Where should this live? Inside TypeConstruction?
3615
func constructExistentialOutputComponent(
3716
from input: Substring,
@@ -61,26 +40,30 @@ func constructExistentialOutputComponent(
6140
return underlying
6241
}
6342

64-
extension StructuredCapture {
43+
@available(SwiftStdlib 5.7, *)
44+
extension AnyRegexOutput.Element {
6545
func existentialOutputComponent(
6646
from input: Substring
6747
) -> Any {
6848
constructExistentialOutputComponent(
6949
from: input,
70-
in: storedCapture?.range,
71-
value: storedCapture?.value,
72-
optionalCount: optionalCount)
50+
in: range,
51+
value: value,
52+
optionalCount: optionalDepth
53+
)
7354
}
7455

7556
func slice(from input: String) -> Substring? {
76-
guard let r = storedCapture?.range else { return nil }
57+
guard let r = range else { return nil }
7758
return input[r]
7859
}
7960
}
8061

81-
extension Sequence where Element == StructuredCapture {
62+
@available(SwiftStdlib 5.7, *)
63+
extension Sequence where Element == AnyRegexOutput.Element {
8264
// FIXME: This is a stop gap where we still slice the input
8365
// and traffic through existentials
66+
@available(SwiftStdlib 5.7, *)
8467
func existentialOutput(
8568
from input: Substring
8669
) -> Any {

Sources/_StringProcessing/Engine/Structuralize.swift

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
@_implementationOnly import _RegexParser
22

33
extension CaptureList {
4-
func structuralize(
4+
@available(SwiftStdlib 5.7, *)
5+
func createElements(
56
_ list: MECaptureList,
67
_ input: String
7-
) -> [StructuredCapture] {
8+
) -> [AnyRegexOutput.ElementRepresentation] {
89
assert(list.values.count == captures.count)
9-
10-
var result = [StructuredCapture]()
11-
for (cap, meStored) in zip(self.captures, list.values) {
12-
let stored = StoredCapture(
13-
range: meStored.latest, value: meStored.latestValue)
14-
15-
result.append(.init(
16-
optionalCount: cap.optionalDepth, storedCapture: stored))
10+
11+
var result = [AnyRegexOutput.ElementRepresentation]()
12+
13+
for (i, (cap, meStored)) in zip(captures, list.values).enumerated() {
14+
let element = AnyRegexOutput.ElementRepresentation(
15+
optionalDepth: cap.optionalDepth,
16+
bounds: meStored.latest,
17+
name: cap.name,
18+
referenceID: list.referencedCaptureOffsets.first { $1 == i }?.key,
19+
value: meStored.latestValue
20+
)
21+
22+
result.append(element)
1723
}
24+
1825
return result
1926
}
2027
}

Sources/_StringProcessing/Executor.swift

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ struct Executor {
4141
namedCaptureOffsets: engine.program.namedCaptureOffsets)
4242

4343
let range = inputRange.lowerBound..<endIdx
44-
let caps = engine.program.captureList.structuralize(capList, input)
44+
let caps = engine.program.captureList.createElements(capList, input)
4545

4646
// FIXME: This is a workaround for not tracking (or
4747
// specially compiling) whole-match values.
@@ -55,14 +55,17 @@ struct Executor {
5555
} else {
5656
value = nil
5757
}
58-
59-
return .init(
58+
59+
let anyRegexOutput = AnyRegexOutput(
6060
input: input,
61+
elements: caps
62+
)
63+
64+
return .init(
65+
anyRegexOutput: anyRegexOutput,
6166
range: range,
62-
rawCaptures: caps,
63-
referencedCaptureOffsets: capList.referencedCaptureOffsets,
64-
namedCaptureOffsets: capList.namedCaptureOffsets,
65-
value: value)
67+
value: value
68+
)
6669
}
6770

6871
@available(SwiftStdlib 5.7, *)

0 commit comments

Comments
 (0)