forked from swiftlang/swift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGenericDispatch.swift
139 lines (118 loc) · 4.51 KB
/
GenericDispatch.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//===--- GenericDispatch.swift - Demonstrate "partial specialization" -----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Do stuff in Swift that we didn't think was possible. This file
// will ensure that the capability doesn't regress and give us a
// prototype to which we can refer when building the standard library.
//
//===----------------------------------------------------------------------===//
// RUN: %target-run-simple-swift | %FileCheck %s
// REQUIRES: executable_test
// CHECK: testing...
print("testing...")
//===----------------------------------------------------------------------===//
//===--- Think of this code as being "in the library" ---------------------===//
//===----------------------------------------------------------------------===//
//===--- F "base" protocol (like ForwardIndex) ----------------------------===//
protocol F {
func successor() -> Self
// This requirement allows generic distance() to find default
// implementations. Only the author of F and the author of a
// refinement of F having a non-default distance implementation need
// to know about it. These refinements are expected to be rare
// (which is why defaulted requirements are a win)
func ~> (_: Self, _: (_Distance, (Self))) -> Int
}
// Operation tag for distance
//
// Operation tags allow us to use a single operator (~>) for
// dispatching every generic function with a default implementation.
// Only authors of specialized distance implementations need to touch
// this tag.
struct _Distance {}
// This function cleans up the syntax of invocations
func _distance<I>(_ other: I) -> (_Distance, (I)) {
return (_Distance(), (other))
}
// Default Implementation of distance for F's
func ~> <I: F>(self_:I, _: (_Distance, (I))) -> Int {
self_.successor() // Use an F-specific operation
print("F")
return 0
}
//===--- Dispatching distance() function ----------------------------------===//
// This generic function is for user consumption; it dispatches to the
// appropriate implementation for T.
func distance<T: F>(_ x: T, _ y: T) -> Int {
return x~>_distance(y)
}
//===--- R refined protocol (like RandomAccessIndex) ----------------------===//
protocol R : F {
// Non-defaulted requirements of R go here, e.g. something to
// measure the distance in O(1)
static func sub(_ x: Self, y: Self)
}
// R has its own default implementation of distance, which is O(1).
// Only the author of R needs to see this implementation.
func ~> <I: R>(x: I, args: (_Distance, (I))) -> Int {
let other = args.1
I.sub(other, y: x)
print("R")
return 1
}
//===--- D refined protocol (like R, but with a custom distance) ----------===//
// Users who want to provide a custom distance function will use this protocol
protocol D : R {
func distance(_ y: Self) -> Int
}
// Dispatch to D's distance() requirement
// Only the author of D needs to see this implementation.
func ~> <I: D>(x: I, args: (_Distance, (I))) -> Int {
let other = args.1
return x.distance(other)
}
//===----------------------------------------------------------------------===//
//===--- Think of this as being "user code" -------------------------------===//
//===----------------------------------------------------------------------===//
// This model of F automatically gets F's default implementation of distance
struct SlowIndex : F {
func successor() -> SlowIndex { return self }
}
// This model of R automatically gets R's default implementation of distance
struct FastIndex : R {
func successor() -> FastIndex { return self }
static func sub(_ x: FastIndex, y: FastIndex) {}
}
struct X : D {
// Customized distance implementation
func distance(_ y: X) -> Int {
print("X")
return 3
}
// Inherited requirements
func successor() -> X { return self }
static func sub(_ x: X, y: X) {}
}
// Here's a generic function that uses our dispatching distance
func sort<T: F>(_ x: T) {
// In here, we don't know whether T is an R or just a plain F, or
// whether it has its own specialized implementation of
distance(x, x)
}
// CHECK-NEXT: F
sort(SlowIndex())
// CHECK-NEXT: R
sort(FastIndex())
// CHECK-NEXT: X
sort(X())
// CHECK-NEXT: done
print("done.")