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)
static 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.")
|