SlideShare une entreprise Scribd logo
1  sur  108
Télécharger pour lire hors ligne
掀起 SWIFT 的⾯面紗
下班⾃我進修裝屌指南
Pofat @ iPlayground
我是 Pofat
Clone 過 Android Source
Code 嗎
讀過 Android Source
Code 嗎?
對 Android Source Code
有什什麼感想?
起源
Swift Source Code 對⼯工作的幫助
0%
如何開始
# Install cmake and ninja
brew install cmake ninja
mkdir swift-source
cd swift-source
# Clone Swift project to local
git clone https://github.com/apple/swift.git
${ROOT} : swift-source here
如何開始 - utils
# use update-checkout update all required
repos
./swift/utils/update-checkout —clone
Compile 前準備
Compile!
# Partially debug message
./swift/utils/build-script --release-debuginfo
# Partially debug message
./swift/utils/build-script --debug
# Partially debug message
./swift/utils/build-script --release
檔案架構
檔案架構
# build path (bin, gyb result, tests…)
${ROOT}/build/Ninja-RelWithDebInfoAssert/
swift-macosx-x86_64
# executables
${ROOT}/build/Ninja-RelWithDebInfoAssert/
swift-macosx-x86_64/bin
${BUILD_ROOT} : ${ROOT}/build/Ninja-RelWithDebInfoAssert/
swift-macosx-x86_64/
檔案架構
# Original source file
${ROOT}/swift/stdlib/public/core
# Converted swift files from gyb
${ROOT}/build/Ninja-RelWithDebInfoAssert/
swift-macosx-x86_64/stdlib/public/core/8
GYB?
gyb --line-directive '' -o 

/path/to/Some.swift Some.swift.gyb
@_fixed_layout
public struct UInt8
: FixedWidthInteger, UnsignedInteger,
_ExpressibleByBuiltinIntegerLiteral {
/// A type that represents an integer literal.
public typealias IntegerLiteralType = UInt8
@_transparent
public init(_builtinIntegerLiteral x:
_MaxBuiltinIntegerType) {
_value = Builtin.s_to_u_checked_trunc_Int2048_Int8(x).0
}
@_transparent
public init(bitPattern x: Int8) {
_value = x._value
}
Tuple
let a = (1, 2, 3, 4, 5, 6)
let b = (1, 2, 3, 4, 5, 6)
print("a == b ? (a == b)")
a == b ? true
Tuple
let c = (1, 2, 3, 4, 5, 6, 7)
let d = (1, 2, 3, 4, 5, 6, 7)
print("c == d ? (c == d)")
error: binary operator '==' cannot be applied
to two '(Int, Int, Int, Int, Int, Int, Int)' operands
Tuple’s GYB
% for arity in range(2,7):

% typeParams = [chr(ord("A") + i) for i in range(arity)]

% tupleT = "({})".format(",".join(typeParams))

% equatableTypeParams = ", ".join(["{} : Equatable".format(c) for c in typeParams])

% originalTuple = "("a", {})".format(", ".join(map(str, range(1, arity))))

% greaterTuple = "("a", {})".format(", ".join(map(str, range(1, arity - 1) + [arity])))
// Tuple.swift.gyb
public func == <A : Comparable, B : Comparable, C :
Comparable, D : Comparable, E : Comparable, F :
Comparable>(lhs: (A,B,C,D,E,F), rhs: (A,B,C,D,E,F)) ->
Bool {

guard lhs.0 == rhs.0 { return false }
return (
lhs.1, lhs.2, lhs.3, lhs.4, lhs.5
) == (
rhs.1, rhs.2, rhs.3, rhs.4, rhs.5
)



}
// Tuple.swift
Optional
@_frozen
public enum Optional<Wrapped> : ExpressibleByNilLiteral {
case none
case some(Wrapped)
@_transparent
public init(_ some: Wrapped) { self = .some(some) }
@_transparent
public init(nilLiteral: ()) {
self = .none
}
}
Optional - Map
public func map<U>(
_ transform: (Wrapped) throws -> U
) rethrows -> U? {

switch self {
case .some(let y):
return .some(try transform(y))
case .none:
return .none
}
}
Optional - flatMap
public func flatMap<U>(
_ transform: (Wrapped) throws -> U
) rethrows -> U? {

switch self {
case .some(let y):
return try transform(y)
case .none:
return .none
}
}
Optional - Unwrap
@_transparent
public func ?? <T>(optional: T?,
defaultValue: @autoclosure () throws ->
T?)
rethrows -> T? {
switch optional {
case .some(let value):
return value
case .none:
return try defaultValue()
}
}
Bool
@_fixed_layout
public struct Bool {
@usableFromInline
internal var _value: Builtin.Int1
public init() {
let zero: Int8 = 0
self._value =
Builtin.trunc_Int8_Int1(zero._value)
}
}
ExpressibleByBooleanLiteral
extension Bool: ExpressibleByBooleanLiteral
{
@_transparent
public init(booleanLiteral value: Bool) {
self = value
}
}
How to @autoclosure
if measurement.count > 0 && sum / Double(measurement.count) < 5 {
// do somehting..
}
measurement.count might be ZERO!!
How to @autoclosure
@_transparent
@inline(__always)
public static func && (
lhs: Bool, rhs: @autoclosure () throws -> Bool)
rethrows -> Bool {
return lhs ? try rhs() : false
}
Attributes
• @inlinable :expose not interface but source code, work
when -O

• @_transparent: must do inline even when -Onone

• @_fixed_layout: Processed at SIL stage. It tells compiler
that access properties by offset is possible without
looking up metadata.



Attributes
• @usableFromInline : Temporarily change scope only
during inline stage. Include @inlinable















@_fixed_layout
public struct Bool {
@usableFromInline
internal var _value: Builtin.Int1
// …
What is Builtin ?
Builtin.Int1

Builtin.trunc_Int8_Int1(zero._value) 



Builtin.s_to_u_checked_trunc_Int2048_Int8(x)
Integer Again
public struct Int
: FixedWidthInteger, SignedInteger,
_ExpressibleByBuiltinIntegerLiteral {


public init(_builtinIntegerLiteral x:
_MaxBuiltinIntegerType) {
_value =
Builtin.s_to_s_checked_trunc_Int2048_Int64(x).0
}
+
public static func +(lhs: Int, rhs: Int) -> Int {
var lhs = lhs
lhs += rhs
return lhs
}
+=
public static func +=(lhs: inout Int, rhs: Int) {
let (result, overflow) =
Builtin.sadd_with_overflow_Int64(
lhs._value, rhs._value, true._value)
Builtin.condfail(overflow)
lhs = Int(result)
}
You may surprise…
• Int is a struct in standard library

• + is a global function declared in standard library

• What an inefficient way !! Do we really implement basic
arithmetic operations by cross-module function calls?



ObjC & Swift Compilation
Clang
Frontend
ObjC
LLVM
LLVM IR Machine Code
Swift
Frontend
Swift
IRGen
SIL Machine Code
LLVM
LLVM IR
Example
// sum.swift
let a = 1
let b = 2
let c = a + b
$swiftc -emit-ir sum.swift
LLVM IR
define i32 @main(i32, i8**) #0 {
entry:
%2 = bitcast i8** %1 to i8*
store i64 1, i64* getelementptr inbounds (%TSi, %TSi*
@"$S4test1aSivp", i32 0, i32 0), align 8
store i64 2, i64* getelementptr inbounds (%TSi, %TSi*
@"$S4test1bSivp", i32 0, i32 0), align 8
%3 = load i64, i64* getelementptr inbounds (%TSi, %TSi*
@"$S4test1aSivp", i32 0, i32 0), align 8
%4 = load i64, i64* getelementptr inbounds (%TSi, %TSi*
@"$S4test1bSivp", i32 0, i32 0), align 8
%5 = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %3,
i64 %4)
%6 = extractvalue { i64, i1 } %5, 0
%7 = extractvalue { i64, i1 } %5, 1
br i1 %7, label %9, label %8
llvm::Intrinsic::ID
swift::getLLVMIntrinsicIDForBuiltinWithOverflow(BuiltinValue
Kind ID) {
switch (ID) {
default: break;
case BuiltinValueKind::SAddOver:
return llvm::Intrinsic::sadd_with_overflow;
case BuiltinValueKind::UAddOver:
return llvm::Intrinsic::uadd_with_overflow;
case BuiltinValueKind::SSubOver:
return llvm::Intrinsic::ssub_with_overflow;
case BuiltinValueKind::USubOver:
return llvm::Intrinsic::usub_with_overflow;
case BuiltinValueKind::SMulOver:
return llvm::Intrinsic::smul_with_overflow;
case BuiltinValueKind::UMulOver:
return llvm::Intrinsic::umul_with_overflow;
}
llvm_unreachable("Cannot convert the overflow builtin to
llvm intrinsic.");
}
${ROOT}/swift/lib/AST/Builtin.cpp
Builtin is a portal
LLVM IR Builtin
Builtin.type
Builtin.method
Standard
Library
TYPE
METHOD
SIL stage
How To Use Builtin.
// builtin_add.swift
import Swift
let (result, overflow) =
Builtin.sadd_with_overflow_Int64(1._value, 2._value,
true._getBuiltinLogicValue())
print(Int(result))
$swiftc -parse-stdlib builtin_add.swift && ./builtin_add
@usableFromInline
// builtin_add.swift
import Swift
let (result, overflow) =
Builtin.sadd_with_overflow_Int64(1._value, 2._value,
true._value)
print(Int(result))
error: '_value' is inaccessible due to 'internal' protection level
Sequence
https://swiftdoc.org/v4.2/protocol/sequence/hierarchy/
Sequence
public protocol Sequence {
associatedtype Element
associatedtype Iterator : IteratorProtocol where
Iterator.Element == Element
func makeIterator() -> Iterator
}

public protocol IteratorProtocol {
mutating func next() -> Element?
}
Sequence
public protocol Sequence {
associatedtype Element
associatedtype Iterator : IteratorProtocol where
Iterator.Element == Element
func makeIterator() -> Iterator
}

public protocol IteratorProtocol {
mutating func next() -> Element?
}
for (index, value) in mySeq.enumerated() {
// do seomthing ...
}
O(1)
Enumerated
/// - Complexity: O(1)
@inlinabl
public func enumerated() -> EnumeratedSequence<Self> {
return EnumeratedSequence(_base: self)
}
Enumerated
public struct EnumeratedSequence<Base: Sequence> {
internal var _base: Base
internal init(_base: Base) {
self._base = _base
}
}
for-in EnumeratedSequence
extension EnumeratedSequence {
public struct Iterator {
internal var _base: Base.Iterator
internal var _count: Int
internal init(_base: Base.Iterator) {
self._base = _base
self._count = 0
}
}
}
for-in EnumeratedSequence
extension EnumeratedSequence.Iterator: IteratorProtocol, Sequence
{
public typealias Element = (offset: Int, element: Base.Element)
public mutating func next() -> Element? {
guard let b = _base.next() else { return nil }
let result = (offset: _count, element: b)
_count += 1
return result
}
}
Map
public func map<T>(
_ transform: (Element) throws -> T
) rethrows -> [T] {

let initialCapacity = underestimatedCount
var result = ContiguousArray<T>()
result.reserveCapacity(initialCapacity)
var iterator = self.makeIterator()
// lower half of map func
Map
// upper half of map func
for _ in 0..<initialCapacity {
result.append(try transform(iterator.next()!))
}
while let element = iterator.next() {
result.append(try transform(element))
}
return Array(result)
}
Reduce
public func reduce<Result>(
_ initialResult: Result,
_ nextPartialResult:
(_ partialResult: Result, Element) throws -> Result
) rethrows -> Result {

var accumulator = initialResult
for element in self {
accumulator = try nextPartialResult(accumulator,
element)
}

return accumulator
}
Reduce Into
public func reduce<Result>(
into initialResult: Result,
_ updateAccumulatingResult:
(_ partialResult: inout Result, Element) throws ->
()
) rethrows -> Result {
var accumulator = initialResult
for element in self {
try updateAccumulatingResult(&accumulator, element)
}
return accumulator
}
}
flatMap
public func flatMap<SegmentOfResult : Sequence>(
_ transform: (Element) throws -> SegmentOfResult
) rethrows -> [SegmentOfResult.Element] {

var result: [SegmentOfResult.Element] = []
for element in self {
result.append(contentsOf: try
transform(element))
}

return result
}
compactMap
public func compactMap<ElementOfResult>(
_ transform: (Element) throws ->
ElementOfResult?
) rethrows -> [ElementOfResult] {

return try _compactMap(transform)

}
public func _compactMap<ElementOfResult>(
_ transform: (Element) throws ->
ElementOfResult?
) rethrows -> [ElementOfResult] {

var result: [ElementOfResult] = []

for element in self {
if let newElement = try transform(element) {
result.append(newElement)
}
}

return result
}
They are EAGER
class FileReadIterator: IteratorProtocol {


private let handler =
FileHandle(forReadingAtPath: "/path/to/large_file")!
func next() -> UInt8? {
let data = handler.readData(ofLength: 1)
return data[0]
}


deinit {
handler.closeFile()
}
}
let fileSequence = AnySequence { FileReadIterator() }

let batchOperation = fileSequence.map{ print($0) }
Make It LAZY
Lazy Sequence
extension Sequence {

public var lazy: LazySequence<Self> {
return LazySequence(_base: self)
}

}
LazySequence
public struct LazySequence<Base : Sequence>:
_SequenceWrapper {

public var _base: Base
internal init(_base: Base) {
self._base = _base
}
}
LazySequenceProtocol
extension LazySequenceProtocol {
public func map<U>(
_ transform: @escaping (Elements.Element) -> U
) -> LazyMapSequence<Self.Elements, U> {
return LazyMapSequence(_base: self.elements,
transform: transform)
}
}
public struct LazyMapSequence<Base : Sequence,
Element> {
internal var _base: Base
internal let _transform: (Base.Element) -> Element
internal init(_base: Base, transform: @escaping
(Base.Element) -> Element) {

self._base = _base
self._transform = transform

}
}
extension LazyMapSequence.Iterator:
IteratorProtocol, Sequence {
public mutating func next() -> Element? {

return _base.next().map(_transform)

}
}
File Reader Revised
let fileSequence = AnySequence { FileReadIterator() }

let lazyBatch = fileSequence.lazy.map{ print($0)}
var batchIterator = lazyBatch.makeIterator()
for _ in 1 ... 10 {
batchIterator.next()
}
File Reader Revised
let fileSequence = AnySequence { FileReadIterator() }

let lazyBatch = fileSequence.lazy.map{ print($0)}
var batchIterator = lazyBatch.makeIterator()
for _ in 1 ... 1024 {
batchIterator.next()
}
Collection
https://swiftdoc.org/v4.2/protocol/collection/hierarchy/
Collection remove(at:)
problem
for obj in objsToDelete {
myCollection.remove(at: myCollection.index(of: obj)!)
}
O(N)
Collection
removeAll(where:)
extension RangeReplaceableCollection {

public mutating func removeAll(
where shouldBeRemoved: (Element) throws -> Bool
) rethrows {

let suffixStart = try _halfStablePartition(isSuffixElement:
shouldBeRemoved)

removeSubrange(suffixStart…)
}
}
mutating func _halfStablePartition(
isSuffixElement: (Element) throws -> Bool
) rethrows -> Index {

guard var i = try firstIndex(where: isSuffixElement)
else { return endIndex }
var j = index(after: i)
while j != endIndex {
if try !isSuffixElement(self[j]) { swapAt(i, j);
formIndex(after: &i) }
formIndex(after: &j)
}

return i
}
mutating func _halfStablePartition(
isSuffixElement: (Element) throws -> Bool
) rethrows -> Index {

guard var i = try firstIndex(where: isSuffixElement)
else { return endIndex }
var j = index(after: i)

while j != endIndex {
if try !isSuffixElement(self[j]) {
swapAt(i, j)
formIndex(after: &i)
}
formIndex(after: &j)
}

return i
}
OH! It’s moving zeros!
Array
Inside Array
public struct Array<Element>: _DestructorSafeContainer {
#if _runtime(_ObjC)
internal typealias _Buffer = _ArrayBuffer<Element>
#endif
internal var _buffer: _Buffer
internal init(_buffer: _Buffer) {
self._buffer = _buffer
}
}
struct Array
_buffer
struct _ArrayBuffer
_storage
struct _BridgStorage
_rawValue
Contiguous Array

or
NSArray
Builtin.BridgeObject
Copy On Write
mutating func append(_ newElement: __owned Element)
{
_makeUniqueAndReserveCapacityIfNotUnique()

let oldCount = _getCount()
_reserveCapacityAssumingUniqueBuffer(oldCount:
oldCount)

_appendElementAssumeUniqueAndCapacity(oldCount,
newElement: newElement)
}
Copy If Not Unique
mutating func _makeUniqueAndReserveCapacityIfNotUnique() {
if _slowPath(!
_buffer.isMutableAndUniquelyReferenced()) {
_copyToNewBuffer(oldCount: _buffer.count)
}
}
isUnique
mutating func isMutableAndUniquelyReferenced() ->
Bool {
return isUniquelyReferenced()
}

isUnique
mutating func isUniquelyReferenced() -> Bool {

if !_isClassOrObjCExistential(Element.self) {
return
_storage.isUniquelyReferenced_native_noSpareBits()
}
if !_storage.isUniquelyReferencedNative() {
return false
}

return _isNative
}

Copy To New Buffer
mutating func _copyToNewBuffer(oldCount: Int) {
let newCount = oldCount + 1
var newBuffer =
_buffer._forceCreateUniqueMutableBuffer(
countForNewBuffer: oldCount, minNewCapacity:
newCount)
_buffer._arrayOutOfPlaceUpdate(&newBuffer,
oldCount, 0)
}
What If Reach Full Capacity
func _forceCreateUniqueMutableBufferImpl(
countForBuffer: Int, minNewCapacity: Int,
requiredCapacity: Int
) -> _ContiguousArrayBuffer<Element> {
let minimumCapacity = Swift.max(requiredCapacity,
minNewCapacity > capacity
? _growArrayCapacity(capacity) : capacity)
return _ContiguousArrayBuffer(
_uninitializedCount: countForBuffer, minimumCapacity:
minimumCapacity)
}
Array Grow
func _growArrayCapacity(_ capacity: Int) -> Int {
return capacity * 2
}
Array Is Not Thread Safe
import Dispatch
var array = [Int]()
DispatchQueue.concurrentPerform(iterations: 50)
{ index in
let last = array.last ?? 0
array.append(last + 1)
}
print("array count: (array.count)")
var array = [1, 2, 3, 4, 5]
let arrayAccessQueue = DispatchQueue(label: "array",
qos: .utility, attributes: .concurrent)
// read
var readValue: Int = 0
arrayAccessQueue.sync {
readValue = array[0]
}
// write
arrayAccessQueue.async(flags: .barrier) {
array.append(6)
}
// thread_safe_access_array.swift
Sorting Array
mutating func sort(
by areInIncreasingOrder: (Element, Element) throws ->
Bool
) rethrows {
let didSortUnsafeBuffer = try
_withUnsafeMutableBufferPointerIfSupported {
buffer -> Void? in
try buffer.sort(by: areInIncreasingOrder)
}
if didSortUnsafeBuffer == nil {
try _introSort(within: startIndex..<endIndex, by:
areInIncreasingOrder)
}
}
Insertion / Intro / Heap
mutating func _introSortImpl(
within range: Range<Index>,
by areInIncreasingOrder: (Element, Element) throws -> Bool,
depthLimit: Int
) rethrows {
if distance(from: range.lowerBound, to: range.upperBound) < 20 {
try _insertionSort(within: range, by: areInIncreasingOrder)
} else if depthLimit == 0 {
try _heapSort(within: range, by: areInIncreasingOrder)
} else {
let partIdx = try _partition(within: range, by: areInIncreasingOrder)
try _introSortImpl(
within: range.lowerBound..<partIdx,
by: areInIncreasingOrder,
depthLimit: depthLimit &- 1)
try _introSortImpl(
within: partIdx..<range.upperBound,
by: areInIncreasingOrder,
depthLimit: depthLimit &- 1)
}
}
Sorting Strategy
mutating func _introSortImpl(
within range: Range<Index>,
by areInIncreasingOrder: (Element, Element) throws -> Bool,
depthLimit: Int
) rethrows {
if distance(from: range.lowerBound, to: range.upperBound) < 20 {
try _insertionSort(within: range, by: areInIncreasingOrder)
} else if depthLimit == 0 {
try _heapSort(within: range, by: areInIncreasingOrder)
} else {
let partIdx = try _partition(within: range, by: areInIncreasingOrder)
try _introSortImpl(
within: range.lowerBound..<partIdx,
by: areInIncreasingOrder,
depthLimit: depthLimit &- 1)
try _introSortImpl(
within: partIdx..<range.upperBound,
by: areInIncreasingOrder,
depthLimit: depthLimit &- 1)
}
}
Sorting Strategy
mutating func _introSortImpl(
within range: Range<Index>,
by areInIncreasingOrder: (Element, Element) throws -> Bool,
depthLimit: Int
) rethrows {
if distance(from: range.lowerBound, to: range.upperBound) < 20 {
try _insertionSort(within: range, by: areInIncreasingOrder)
} else if depthLimit == 0 {
try _heapSort(within: range, by: areInIncreasingOrder)
} else {
let partIdx = try _partition(within: range, by: areInIncreasingOrder)
try _introSortImpl(
within: range.lowerBound..<partIdx,
by: areInIncreasingOrder,
depthLimit: depthLimit &- 1)
try _introSortImpl(
within: partIdx..<range.upperBound,
by: areInIncreasingOrder,
depthLimit: depthLimit &- 1)
}
}
Develop Swift !!
Better Reduce:
User first element in sequence as initial value
Test FIRST!
SequenceTypeTests.test("betterReduce") {
let animals = ["Antelope", "Butterfly", "Camel",
“Dolphin"]
var timesClosureWasCalled = 0
let longestAnimal = animals.betterReduce
{ current, animal in
timesClousreWasCalled += 1
if current.count > animal.count {
return current
} else {
return animal
}
} ?? “"
// expects …
}
// ${ROOT}/swift/validation-test/stdlib/SequenceType.swift.gyb
SequenceTypeTests.test("betterReduce") {
// Codes …
expectEqual(longestAnimal, “Butterfly")
expectEqual(
animals.count, timesClosureWasCalled,
"betterReduce() should be eager”)
}
// ${ROOT}/swift/validation-test/stdlib/SequenceType.swift.gyb
Now CODE!!
// SequenceAlgorithm.swift — extension Sequence
@inlinable
public func betterReduce(
_ nextPartialResult:
(_ partialResult: Element, Element) throws -> Element
) rethrows -> Element? {

var i = makeIterator()
guard var accumulated = i.next() else {
return nil
}
while let element = i.next() {
accumulated = try nextPartialResult(accumulated,
element)
}
return accumulated
}
Test Swift!!
./swift/utils/build-script -r -tCompile and test
./swift/utils/build-script -r -T
Compile and
validation test
4XXX tests!!
10000+ tests!!
Test Standard Library Only
./llvm/utils/lit/lit.py -sv ${BUILD_ROOT}/swift-
macosx-x86_64/test-macosx-x86_64/stdlib
A full-test run is suggested in the first place
./llvm/utils/lit/lit.py -sv ${BUILD_ROOT}/
swift-macosx-x86_64/validation-test-macosx-
x86_64/stdlib
sh ${BUILD_ROOT}/validation-test-macosx-x86_64/stdlib/Output/
Bool.swift.script
Now you can do single test with
Wait!
Not compiled yet…
${BUILD_ROOT} ninja swift-stdlib
Thanks to ninja, lets build standard library only
sh ${BUILD_RTTO}/validation-test-macosx-x86_64/

stdlib/Output/SequenceType.swift.gyb.script
And do test!!
😎
所以,看 Source
Code到底有何幫助??
參參考來來源
• https://github.com/apple/swift

• 喵神 Swift 标准库源码导读 
我的裝屌指南系列列
• EP I: GitHub 裝屌指南

• EP II: Vim 裝屌指南

• EP III: Debug 裝屌指南
講完惹
關愛 Swift 發展者或想討論 ,歡迎和我聯聯繫 tjazzterATgmailDOTcom

Contenu connexe

Tendances

Java Bytecode Fundamentals - JUG.lv
Java Bytecode Fundamentals - JUG.lvJava Bytecode Fundamentals - JUG.lv
Java Bytecode Fundamentals - JUG.lv
Anton Arhipov
 
Php Extensions for Dummies
Php Extensions for DummiesPhp Extensions for Dummies
Php Extensions for Dummies
Elizabeth Smith
 
C++11: Feel the New Language
C++11: Feel the New LanguageC++11: Feel the New Language
C++11: Feel the New Language
mspline
 
Unit 5
Unit 5Unit 5
Unit 5
siddr
 

Tendances (20)

Google Edge TPUで TensorFlow Liteを使った時に 何をやっているのかを妄想してみる 2 「エッジAIモダン計測制御の世界」オ...
Google Edge TPUで TensorFlow Liteを使った時に 何をやっているのかを妄想してみる 2  「エッジAIモダン計測制御の世界」オ...Google Edge TPUで TensorFlow Liteを使った時に 何をやっているのかを妄想してみる 2  「エッジAIモダン計測制御の世界」オ...
Google Edge TPUで TensorFlow Liteを使った時に 何をやっているのかを妄想してみる 2 「エッジAIモダン計測制御の世界」オ...
 
PHP Performance Trivia
PHP Performance TriviaPHP Performance Trivia
PHP Performance Trivia
 
Kotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRreadyKotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRready
 
HKG15-207: Advanced Toolchain Usage Part 3
HKG15-207: Advanced Toolchain Usage Part 3HKG15-207: Advanced Toolchain Usage Part 3
HKG15-207: Advanced Toolchain Usage Part 3
 
Java Bytecode Fundamentals - JUG.lv
Java Bytecode Fundamentals - JUG.lvJava Bytecode Fundamentals - JUG.lv
Java Bytecode Fundamentals - JUG.lv
 
Metaprogramming and Reflection in Common Lisp
Metaprogramming and Reflection in Common LispMetaprogramming and Reflection in Common Lisp
Metaprogramming and Reflection in Common Lisp
 
OpenGurukul : Language : C++ Programming
OpenGurukul : Language : C++ ProgrammingOpenGurukul : Language : C++ Programming
OpenGurukul : Language : C++ Programming
 
Modern C++
Modern C++Modern C++
Modern C++
 
Constructor,destructors cpp
Constructor,destructors cppConstructor,destructors cpp
Constructor,destructors cpp
 
Lean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, Gett
Lean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, GettLean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, Gett
Lean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, Gett
 
Php Extensions for Dummies
Php Extensions for DummiesPhp Extensions for Dummies
Php Extensions for Dummies
 
C++aptitude questions and answers
C++aptitude questions and answersC++aptitude questions and answers
C++aptitude questions and answers
 
Functional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis AtencioFunctional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis Atencio
 
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1
 
C++11: Feel the New Language
C++11: Feel the New LanguageC++11: Feel the New Language
C++11: Feel the New Language
 
Nikita Popov "What’s new in PHP 8.0?"
Nikita Popov "What’s new in PHP 8.0?"Nikita Popov "What’s new in PHP 8.0?"
Nikita Popov "What’s new in PHP 8.0?"
 
Unit 5
Unit 5Unit 5
Unit 5
 
The bytecode hocus pocus - JavaOne 2016
The bytecode hocus pocus - JavaOne 2016The bytecode hocus pocus - JavaOne 2016
The bytecode hocus pocus - JavaOne 2016
 
What's in Kotlin for us - Alexandre Greschon, MyHeritage
What's in Kotlin for us - Alexandre Greschon, MyHeritageWhat's in Kotlin for us - Alexandre Greschon, MyHeritage
What's in Kotlin for us - Alexandre Greschon, MyHeritage
 
TensorFlow local Python XLA client
TensorFlow local Python XLA clientTensorFlow local Python XLA client
TensorFlow local Python XLA client
 

Similaire à 掀起 Swift 的面紗

An Overview Of Python With Functional Programming
An Overview Of Python With Functional ProgrammingAn Overview Of Python With Functional Programming
An Overview Of Python With Functional Programming
Adam Getchell
 

Similaire à 掀起 Swift 的面紗 (20)

Cluj.py Meetup: Extending Python in C
Cluj.py Meetup: Extending Python in CCluj.py Meetup: Extending Python in C
Cluj.py Meetup: Extending Python in C
 
An Overview Of Python With Functional Programming
An Overview Of Python With Functional ProgrammingAn Overview Of Python With Functional Programming
An Overview Of Python With Functional Programming
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?
 
Cocoa heads 09112017
Cocoa heads 09112017Cocoa heads 09112017
Cocoa heads 09112017
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015
 
C# 6.0 Preview
C# 6.0 PreviewC# 6.0 Preview
C# 6.0 Preview
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)
 
Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing Speed
 
Silicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsSilicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM Mechanics
 
Things about Functional JavaScript
Things about Functional JavaScriptThings about Functional JavaScript
Things about Functional JavaScript
 
NetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf EditionNetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf Edition
 
Swift on Raspberry Pi
Swift on Raspberry PiSwift on Raspberry Pi
Swift on Raspberry Pi
 
Lies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerLies Told By The Kotlin Compiler
Lies Told By The Kotlin Compiler
 
1183 c-interview-questions-and-answers
1183 c-interview-questions-and-answers1183 c-interview-questions-and-answers
1183 c-interview-questions-and-answers
 
The Swift Compiler and Standard Library
The Swift Compiler and Standard LibraryThe Swift Compiler and Standard Library
The Swift Compiler and Standard Library
 
Scala is java8.next()
Scala is java8.next()Scala is java8.next()
Scala is java8.next()
 
Appsec obfuscator reloaded
Appsec obfuscator reloadedAppsec obfuscator reloaded
Appsec obfuscator reloaded
 
Pragmatic Optimization in Modern Programming - Demystifying the Compiler
Pragmatic Optimization in Modern Programming - Demystifying the CompilerPragmatic Optimization in Modern Programming - Demystifying the Compiler
Pragmatic Optimization in Modern Programming - Demystifying the Compiler
 
Multiplatform JIT Code Generator for NetBSD by Alexander Nasonov
Multiplatform JIT Code Generator for NetBSD by Alexander NasonovMultiplatform JIT Code Generator for NetBSD by Alexander Nasonov
Multiplatform JIT Code Generator for NetBSD by Alexander Nasonov
 

Dernier

Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
Christo Ananth
 
AKTU Computer Networks notes --- Unit 3.pdf
AKTU Computer Networks notes ---  Unit 3.pdfAKTU Computer Networks notes ---  Unit 3.pdf
AKTU Computer Networks notes --- Unit 3.pdf
ankushspencer015
 
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Dr.Costas Sachpazis
 

Dernier (20)

Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
 
Coefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxCoefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptx
 
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
Call Girls in Nagpur Suman Call 7001035870 Meet With Nagpur Escorts
 
Introduction and different types of Ethernet.pptx
Introduction and different types of Ethernet.pptxIntroduction and different types of Ethernet.pptx
Introduction and different types of Ethernet.pptx
 
UNIT-III FMM. DIMENSIONAL ANALYSIS
UNIT-III FMM.        DIMENSIONAL ANALYSISUNIT-III FMM.        DIMENSIONAL ANALYSIS
UNIT-III FMM. DIMENSIONAL ANALYSIS
 
Booking open Available Pune Call Girls Pargaon 6297143586 Call Hot Indian Gi...
Booking open Available Pune Call Girls Pargaon  6297143586 Call Hot Indian Gi...Booking open Available Pune Call Girls Pargaon  6297143586 Call Hot Indian Gi...
Booking open Available Pune Call Girls Pargaon 6297143586 Call Hot Indian Gi...
 
Processing & Properties of Floor and Wall Tiles.pptx
Processing & Properties of Floor and Wall Tiles.pptxProcessing & Properties of Floor and Wall Tiles.pptx
Processing & Properties of Floor and Wall Tiles.pptx
 
Online banking management system project.pdf
Online banking management system project.pdfOnline banking management system project.pdf
Online banking management system project.pdf
 
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINEMANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
 
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...
 
University management System project report..pdf
University management System project report..pdfUniversity management System project report..pdf
University management System project report..pdf
 
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service NashikCall Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
 
College Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service NashikCollege Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
 
Water Industry Process Automation & Control Monthly - April 2024
Water Industry Process Automation & Control Monthly - April 2024Water Industry Process Automation & Control Monthly - April 2024
Water Industry Process Automation & Control Monthly - April 2024
 
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
 
DJARUM4D - SLOT GACOR ONLINE | SLOT DEMO ONLINE
DJARUM4D - SLOT GACOR ONLINE | SLOT DEMO ONLINEDJARUM4D - SLOT GACOR ONLINE | SLOT DEMO ONLINE
DJARUM4D - SLOT GACOR ONLINE | SLOT DEMO ONLINE
 
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur EscortsHigh Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
 
AKTU Computer Networks notes --- Unit 3.pdf
AKTU Computer Networks notes ---  Unit 3.pdfAKTU Computer Networks notes ---  Unit 3.pdf
AKTU Computer Networks notes --- Unit 3.pdf
 
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
 
(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
 

掀起 Swift 的面紗

  • 3. Clone 過 Android Source Code 嗎 讀過 Android Source Code 嗎? 對 Android Source Code 有什什麼感想? 起源
  • 4. Swift Source Code 對⼯工作的幫助 0%
  • 5. 如何開始 # Install cmake and ninja brew install cmake ninja mkdir swift-source cd swift-source # Clone Swift project to local git clone https://github.com/apple/swift.git ${ROOT} : swift-source here
  • 7. # use update-checkout update all required repos ./swift/utils/update-checkout —clone
  • 9. Compile! # Partially debug message ./swift/utils/build-script --release-debuginfo # Partially debug message ./swift/utils/build-script --debug # Partially debug message ./swift/utils/build-script --release
  • 11. 檔案架構 # build path (bin, gyb result, tests…) ${ROOT}/build/Ninja-RelWithDebInfoAssert/ swift-macosx-x86_64 # executables ${ROOT}/build/Ninja-RelWithDebInfoAssert/ swift-macosx-x86_64/bin ${BUILD_ROOT} : ${ROOT}/build/Ninja-RelWithDebInfoAssert/ swift-macosx-x86_64/
  • 12. 檔案架構 # Original source file ${ROOT}/swift/stdlib/public/core # Converted swift files from gyb ${ROOT}/build/Ninja-RelWithDebInfoAssert/ swift-macosx-x86_64/stdlib/public/core/8
  • 13. GYB? gyb --line-directive '' -o 
 /path/to/Some.swift Some.swift.gyb
  • 14. @_fixed_layout public struct UInt8 : FixedWidthInteger, UnsignedInteger, _ExpressibleByBuiltinIntegerLiteral { /// A type that represents an integer literal. public typealias IntegerLiteralType = UInt8 @_transparent public init(_builtinIntegerLiteral x: _MaxBuiltinIntegerType) { _value = Builtin.s_to_u_checked_trunc_Int2048_Int8(x).0 } @_transparent public init(bitPattern x: Int8) { _value = x._value }
  • 15. Tuple let a = (1, 2, 3, 4, 5, 6) let b = (1, 2, 3, 4, 5, 6) print("a == b ? (a == b)") a == b ? true
  • 16. Tuple let c = (1, 2, 3, 4, 5, 6, 7) let d = (1, 2, 3, 4, 5, 6, 7) print("c == d ? (c == d)") error: binary operator '==' cannot be applied to two '(Int, Int, Int, Int, Int, Int, Int)' operands
  • 17. Tuple’s GYB % for arity in range(2,7): % typeParams = [chr(ord("A") + i) for i in range(arity)] % tupleT = "({})".format(",".join(typeParams)) % equatableTypeParams = ", ".join(["{} : Equatable".format(c) for c in typeParams]) % originalTuple = "("a", {})".format(", ".join(map(str, range(1, arity)))) % greaterTuple = "("a", {})".format(", ".join(map(str, range(1, arity - 1) + [arity]))) // Tuple.swift.gyb
  • 18. public func == <A : Comparable, B : Comparable, C : Comparable, D : Comparable, E : Comparable, F : Comparable>(lhs: (A,B,C,D,E,F), rhs: (A,B,C,D,E,F)) -> Bool {
 guard lhs.0 == rhs.0 { return false } return ( lhs.1, lhs.2, lhs.3, lhs.4, lhs.5 ) == ( rhs.1, rhs.2, rhs.3, rhs.4, rhs.5 )
 
 } // Tuple.swift
  • 19. Optional @_frozen public enum Optional<Wrapped> : ExpressibleByNilLiteral { case none case some(Wrapped) @_transparent public init(_ some: Wrapped) { self = .some(some) } @_transparent public init(nilLiteral: ()) { self = .none } }
  • 20. Optional - Map public func map<U>( _ transform: (Wrapped) throws -> U ) rethrows -> U? {
 switch self { case .some(let y): return .some(try transform(y)) case .none: return .none } }
  • 21. Optional - flatMap public func flatMap<U>( _ transform: (Wrapped) throws -> U ) rethrows -> U? {
 switch self { case .some(let y): return try transform(y) case .none: return .none } }
  • 22. Optional - Unwrap @_transparent public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T?) rethrows -> T? { switch optional { case .some(let value): return value case .none: return try defaultValue() } }
  • 23. Bool @_fixed_layout public struct Bool { @usableFromInline internal var _value: Builtin.Int1 public init() { let zero: Int8 = 0 self._value = Builtin.trunc_Int8_Int1(zero._value) } }
  • 25. How to @autoclosure if measurement.count > 0 && sum / Double(measurement.count) < 5 { // do somehting.. } measurement.count might be ZERO!!
  • 26. How to @autoclosure @_transparent @inline(__always) public static func && ( lhs: Bool, rhs: @autoclosure () throws -> Bool) rethrows -> Bool { return lhs ? try rhs() : false }
  • 27. Attributes • @inlinable :expose not interface but source code, work when -O • @_transparent: must do inline even when -Onone • @_fixed_layout: Processed at SIL stage. It tells compiler that access properties by offset is possible without looking up metadata.
 

  • 28. Attributes • @usableFromInline : Temporarily change scope only during inline stage. Include @inlinable
 
 
 
 
 
 
 
 @_fixed_layout public struct Bool { @usableFromInline internal var _value: Builtin.Int1 // …
  • 29. What is Builtin ? Builtin.Int1
 Builtin.trunc_Int8_Int1(zero._value) 
 
 Builtin.s_to_u_checked_trunc_Int2048_Int8(x)
  • 30. Integer Again public struct Int : FixedWidthInteger, SignedInteger, _ExpressibleByBuiltinIntegerLiteral { 
 public init(_builtinIntegerLiteral x: _MaxBuiltinIntegerType) { _value = Builtin.s_to_s_checked_trunc_Int2048_Int64(x).0 }
  • 31. + public static func +(lhs: Int, rhs: Int) -> Int { var lhs = lhs lhs += rhs return lhs }
  • 32. += public static func +=(lhs: inout Int, rhs: Int) { let (result, overflow) = Builtin.sadd_with_overflow_Int64( lhs._value, rhs._value, true._value) Builtin.condfail(overflow) lhs = Int(result) }
  • 33. You may surprise… • Int is a struct in standard library • + is a global function declared in standard library • What an inefficient way !! Do we really implement basic arithmetic operations by cross-module function calls?
 

  • 34.
  • 35. ObjC & Swift Compilation Clang Frontend ObjC LLVM LLVM IR Machine Code Swift Frontend Swift IRGen SIL Machine Code LLVM LLVM IR
  • 36. Example // sum.swift let a = 1 let b = 2 let c = a + b $swiftc -emit-ir sum.swift
  • 37. LLVM IR define i32 @main(i32, i8**) #0 { entry: %2 = bitcast i8** %1 to i8* store i64 1, i64* getelementptr inbounds (%TSi, %TSi* @"$S4test1aSivp", i32 0, i32 0), align 8 store i64 2, i64* getelementptr inbounds (%TSi, %TSi* @"$S4test1bSivp", i32 0, i32 0), align 8 %3 = load i64, i64* getelementptr inbounds (%TSi, %TSi* @"$S4test1aSivp", i32 0, i32 0), align 8 %4 = load i64, i64* getelementptr inbounds (%TSi, %TSi* @"$S4test1bSivp", i32 0, i32 0), align 8 %5 = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %3, i64 %4) %6 = extractvalue { i64, i1 } %5, 0 %7 = extractvalue { i64, i1 } %5, 1 br i1 %7, label %9, label %8
  • 38. llvm::Intrinsic::ID swift::getLLVMIntrinsicIDForBuiltinWithOverflow(BuiltinValue Kind ID) { switch (ID) { default: break; case BuiltinValueKind::SAddOver: return llvm::Intrinsic::sadd_with_overflow; case BuiltinValueKind::UAddOver: return llvm::Intrinsic::uadd_with_overflow; case BuiltinValueKind::SSubOver: return llvm::Intrinsic::ssub_with_overflow; case BuiltinValueKind::USubOver: return llvm::Intrinsic::usub_with_overflow; case BuiltinValueKind::SMulOver: return llvm::Intrinsic::smul_with_overflow; case BuiltinValueKind::UMulOver: return llvm::Intrinsic::umul_with_overflow; } llvm_unreachable("Cannot convert the overflow builtin to llvm intrinsic."); } ${ROOT}/swift/lib/AST/Builtin.cpp
  • 39. Builtin is a portal LLVM IR Builtin Builtin.type Builtin.method Standard Library TYPE METHOD SIL stage
  • 40. How To Use Builtin. // builtin_add.swift import Swift let (result, overflow) = Builtin.sadd_with_overflow_Int64(1._value, 2._value, true._getBuiltinLogicValue()) print(Int(result)) $swiftc -parse-stdlib builtin_add.swift && ./builtin_add
  • 41. @usableFromInline // builtin_add.swift import Swift let (result, overflow) = Builtin.sadd_with_overflow_Int64(1._value, 2._value, true._value) print(Int(result)) error: '_value' is inaccessible due to 'internal' protection level
  • 43. Sequence public protocol Sequence { associatedtype Element associatedtype Iterator : IteratorProtocol where Iterator.Element == Element func makeIterator() -> Iterator }
 public protocol IteratorProtocol { mutating func next() -> Element? }
  • 44. Sequence public protocol Sequence { associatedtype Element associatedtype Iterator : IteratorProtocol where Iterator.Element == Element func makeIterator() -> Iterator }
 public protocol IteratorProtocol { mutating func next() -> Element? }
  • 45. for (index, value) in mySeq.enumerated() { // do seomthing ... } O(1)
  • 46. Enumerated /// - Complexity: O(1) @inlinabl public func enumerated() -> EnumeratedSequence<Self> { return EnumeratedSequence(_base: self) }
  • 47. Enumerated public struct EnumeratedSequence<Base: Sequence> { internal var _base: Base internal init(_base: Base) { self._base = _base } }
  • 48. for-in EnumeratedSequence extension EnumeratedSequence { public struct Iterator { internal var _base: Base.Iterator internal var _count: Int internal init(_base: Base.Iterator) { self._base = _base self._count = 0 } } }
  • 49. for-in EnumeratedSequence extension EnumeratedSequence.Iterator: IteratorProtocol, Sequence { public typealias Element = (offset: Int, element: Base.Element) public mutating func next() -> Element? { guard let b = _base.next() else { return nil } let result = (offset: _count, element: b) _count += 1 return result } }
  • 50. Map public func map<T>( _ transform: (Element) throws -> T ) rethrows -> [T] {
 let initialCapacity = underestimatedCount var result = ContiguousArray<T>() result.reserveCapacity(initialCapacity) var iterator = self.makeIterator() // lower half of map func
  • 51. Map // upper half of map func for _ in 0..<initialCapacity { result.append(try transform(iterator.next()!)) } while let element = iterator.next() { result.append(try transform(element)) } return Array(result) }
  • 52. Reduce public func reduce<Result>( _ initialResult: Result, _ nextPartialResult: (_ partialResult: Result, Element) throws -> Result ) rethrows -> Result {
 var accumulator = initialResult for element in self { accumulator = try nextPartialResult(accumulator, element) }
 return accumulator }
  • 53. Reduce Into public func reduce<Result>( into initialResult: Result, _ updateAccumulatingResult: (_ partialResult: inout Result, Element) throws -> () ) rethrows -> Result { var accumulator = initialResult for element in self { try updateAccumulatingResult(&accumulator, element) } return accumulator } }
  • 54. flatMap public func flatMap<SegmentOfResult : Sequence>( _ transform: (Element) throws -> SegmentOfResult ) rethrows -> [SegmentOfResult.Element] {
 var result: [SegmentOfResult.Element] = [] for element in self { result.append(contentsOf: try transform(element)) }
 return result }
  • 55. compactMap public func compactMap<ElementOfResult>( _ transform: (Element) throws -> ElementOfResult? ) rethrows -> [ElementOfResult] {
 return try _compactMap(transform)
 }
  • 56. public func _compactMap<ElementOfResult>( _ transform: (Element) throws -> ElementOfResult? ) rethrows -> [ElementOfResult] {
 var result: [ElementOfResult] = []
 for element in self { if let newElement = try transform(element) { result.append(newElement) } }
 return result }
  • 58. class FileReadIterator: IteratorProtocol { 
 private let handler = FileHandle(forReadingAtPath: "/path/to/large_file")! func next() -> UInt8? { let data = handler.readData(ofLength: 1) return data[0] } 
 deinit { handler.closeFile() } }
  • 59. let fileSequence = AnySequence { FileReadIterator() }
 let batchOperation = fileSequence.map{ print($0) }
  • 61. Lazy Sequence extension Sequence {
 public var lazy: LazySequence<Self> { return LazySequence(_base: self) }
 }
  • 62. LazySequence public struct LazySequence<Base : Sequence>: _SequenceWrapper {
 public var _base: Base internal init(_base: Base) { self._base = _base } }
  • 63. LazySequenceProtocol extension LazySequenceProtocol { public func map<U>( _ transform: @escaping (Elements.Element) -> U ) -> LazyMapSequence<Self.Elements, U> { return LazyMapSequence(_base: self.elements, transform: transform) } }
  • 64. public struct LazyMapSequence<Base : Sequence, Element> { internal var _base: Base internal let _transform: (Base.Element) -> Element internal init(_base: Base, transform: @escaping (Base.Element) -> Element) {
 self._base = _base self._transform = transform
 } }
  • 65. extension LazyMapSequence.Iterator: IteratorProtocol, Sequence { public mutating func next() -> Element? {
 return _base.next().map(_transform)
 } }
  • 66. File Reader Revised let fileSequence = AnySequence { FileReadIterator() }
 let lazyBatch = fileSequence.lazy.map{ print($0)} var batchIterator = lazyBatch.makeIterator() for _ in 1 ... 10 { batchIterator.next() }
  • 67. File Reader Revised let fileSequence = AnySequence { FileReadIterator() }
 let lazyBatch = fileSequence.lazy.map{ print($0)} var batchIterator = lazyBatch.makeIterator() for _ in 1 ... 1024 { batchIterator.next() }
  • 69. Collection remove(at:) problem for obj in objsToDelete { myCollection.remove(at: myCollection.index(of: obj)!) } O(N)
  • 70. Collection removeAll(where:) extension RangeReplaceableCollection {
 public mutating func removeAll( where shouldBeRemoved: (Element) throws -> Bool ) rethrows {
 let suffixStart = try _halfStablePartition(isSuffixElement: shouldBeRemoved)
 removeSubrange(suffixStart…) } }
  • 71. mutating func _halfStablePartition( isSuffixElement: (Element) throws -> Bool ) rethrows -> Index {
 guard var i = try firstIndex(where: isSuffixElement) else { return endIndex } var j = index(after: i) while j != endIndex { if try !isSuffixElement(self[j]) { swapAt(i, j); formIndex(after: &i) } formIndex(after: &j) }
 return i }
  • 72. mutating func _halfStablePartition( isSuffixElement: (Element) throws -> Bool ) rethrows -> Index {
 guard var i = try firstIndex(where: isSuffixElement) else { return endIndex } var j = index(after: i)
 while j != endIndex { if try !isSuffixElement(self[j]) { swapAt(i, j) formIndex(after: &i) } formIndex(after: &j) }
 return i } OH! It’s moving zeros!
  • 73. Array
  • 74. Inside Array public struct Array<Element>: _DestructorSafeContainer { #if _runtime(_ObjC) internal typealias _Buffer = _ArrayBuffer<Element> #endif internal var _buffer: _Buffer internal init(_buffer: _Buffer) { self._buffer = _buffer } }
  • 75. struct Array _buffer struct _ArrayBuffer _storage struct _BridgStorage _rawValue Contiguous Array
 or NSArray Builtin.BridgeObject
  • 76.
  • 77. Copy On Write mutating func append(_ newElement: __owned Element) { _makeUniqueAndReserveCapacityIfNotUnique()
 let oldCount = _getCount() _reserveCapacityAssumingUniqueBuffer(oldCount: oldCount)
 _appendElementAssumeUniqueAndCapacity(oldCount, newElement: newElement) }
  • 78. Copy If Not Unique mutating func _makeUniqueAndReserveCapacityIfNotUnique() { if _slowPath(! _buffer.isMutableAndUniquelyReferenced()) { _copyToNewBuffer(oldCount: _buffer.count) } }
  • 79. isUnique mutating func isMutableAndUniquelyReferenced() -> Bool { return isUniquelyReferenced() }

  • 80. isUnique mutating func isUniquelyReferenced() -> Bool {
 if !_isClassOrObjCExistential(Element.self) { return _storage.isUniquelyReferenced_native_noSpareBits() } if !_storage.isUniquelyReferencedNative() { return false }
 return _isNative }

  • 81. Copy To New Buffer mutating func _copyToNewBuffer(oldCount: Int) { let newCount = oldCount + 1 var newBuffer = _buffer._forceCreateUniqueMutableBuffer( countForNewBuffer: oldCount, minNewCapacity: newCount) _buffer._arrayOutOfPlaceUpdate(&newBuffer, oldCount, 0) }
  • 82. What If Reach Full Capacity func _forceCreateUniqueMutableBufferImpl( countForBuffer: Int, minNewCapacity: Int, requiredCapacity: Int ) -> _ContiguousArrayBuffer<Element> { let minimumCapacity = Swift.max(requiredCapacity, minNewCapacity > capacity ? _growArrayCapacity(capacity) : capacity) return _ContiguousArrayBuffer( _uninitializedCount: countForBuffer, minimumCapacity: minimumCapacity) }
  • 83. Array Grow func _growArrayCapacity(_ capacity: Int) -> Int { return capacity * 2 }
  • 84. Array Is Not Thread Safe import Dispatch var array = [Int]() DispatchQueue.concurrentPerform(iterations: 50) { index in let last = array.last ?? 0 array.append(last + 1) } print("array count: (array.count)")
  • 85. var array = [1, 2, 3, 4, 5] let arrayAccessQueue = DispatchQueue(label: "array", qos: .utility, attributes: .concurrent) // read var readValue: Int = 0 arrayAccessQueue.sync { readValue = array[0] } // write arrayAccessQueue.async(flags: .barrier) { array.append(6) } // thread_safe_access_array.swift
  • 86. Sorting Array mutating func sort( by areInIncreasingOrder: (Element, Element) throws -> Bool ) rethrows { let didSortUnsafeBuffer = try _withUnsafeMutableBufferPointerIfSupported { buffer -> Void? in try buffer.sort(by: areInIncreasingOrder) } if didSortUnsafeBuffer == nil { try _introSort(within: startIndex..<endIndex, by: areInIncreasingOrder) } }
  • 87. Insertion / Intro / Heap mutating func _introSortImpl( within range: Range<Index>, by areInIncreasingOrder: (Element, Element) throws -> Bool, depthLimit: Int ) rethrows { if distance(from: range.lowerBound, to: range.upperBound) < 20 { try _insertionSort(within: range, by: areInIncreasingOrder) } else if depthLimit == 0 { try _heapSort(within: range, by: areInIncreasingOrder) } else { let partIdx = try _partition(within: range, by: areInIncreasingOrder) try _introSortImpl( within: range.lowerBound..<partIdx, by: areInIncreasingOrder, depthLimit: depthLimit &- 1) try _introSortImpl( within: partIdx..<range.upperBound, by: areInIncreasingOrder, depthLimit: depthLimit &- 1) } }
  • 88. Sorting Strategy mutating func _introSortImpl( within range: Range<Index>, by areInIncreasingOrder: (Element, Element) throws -> Bool, depthLimit: Int ) rethrows { if distance(from: range.lowerBound, to: range.upperBound) < 20 { try _insertionSort(within: range, by: areInIncreasingOrder) } else if depthLimit == 0 { try _heapSort(within: range, by: areInIncreasingOrder) } else { let partIdx = try _partition(within: range, by: areInIncreasingOrder) try _introSortImpl( within: range.lowerBound..<partIdx, by: areInIncreasingOrder, depthLimit: depthLimit &- 1) try _introSortImpl( within: partIdx..<range.upperBound, by: areInIncreasingOrder, depthLimit: depthLimit &- 1) } }
  • 89. Sorting Strategy mutating func _introSortImpl( within range: Range<Index>, by areInIncreasingOrder: (Element, Element) throws -> Bool, depthLimit: Int ) rethrows { if distance(from: range.lowerBound, to: range.upperBound) < 20 { try _insertionSort(within: range, by: areInIncreasingOrder) } else if depthLimit == 0 { try _heapSort(within: range, by: areInIncreasingOrder) } else { let partIdx = try _partition(within: range, by: areInIncreasingOrder) try _introSortImpl( within: range.lowerBound..<partIdx, by: areInIncreasingOrder, depthLimit: depthLimit &- 1) try _introSortImpl( within: partIdx..<range.upperBound, by: areInIncreasingOrder, depthLimit: depthLimit &- 1) } }
  • 90. Develop Swift !! Better Reduce: User first element in sequence as initial value
  • 92. SequenceTypeTests.test("betterReduce") { let animals = ["Antelope", "Butterfly", "Camel", “Dolphin"] var timesClosureWasCalled = 0 let longestAnimal = animals.betterReduce { current, animal in timesClousreWasCalled += 1 if current.count > animal.count { return current } else { return animal } } ?? “" // expects … } // ${ROOT}/swift/validation-test/stdlib/SequenceType.swift.gyb
  • 93. SequenceTypeTests.test("betterReduce") { // Codes … expectEqual(longestAnimal, “Butterfly") expectEqual( animals.count, timesClosureWasCalled, "betterReduce() should be eager”) } // ${ROOT}/swift/validation-test/stdlib/SequenceType.swift.gyb
  • 95. // SequenceAlgorithm.swift — extension Sequence @inlinable public func betterReduce( _ nextPartialResult: (_ partialResult: Element, Element) throws -> Element ) rethrows -> Element? {
 var i = makeIterator() guard var accumulated = i.next() else { return nil } while let element = i.next() { accumulated = try nextPartialResult(accumulated, element) } return accumulated }
  • 96. Test Swift!! ./swift/utils/build-script -r -tCompile and test ./swift/utils/build-script -r -T Compile and validation test 4XXX tests!! 10000+ tests!!
  • 97. Test Standard Library Only ./llvm/utils/lit/lit.py -sv ${BUILD_ROOT}/swift- macosx-x86_64/test-macosx-x86_64/stdlib A full-test run is suggested in the first place ./llvm/utils/lit/lit.py -sv ${BUILD_ROOT}/ swift-macosx-x86_64/validation-test-macosx- x86_64/stdlib
  • 98.
  • 101. ${BUILD_ROOT} ninja swift-stdlib Thanks to ninja, lets build standard library only sh ${BUILD_RTTO}/validation-test-macosx-x86_64/
 stdlib/Output/SequenceType.swift.gyb.script And do test!!
  • 102. 😎
  • 103.
  • 105.
  • 107. 我的裝屌指南系列列 • EP I: GitHub 裝屌指南 • EP II: Vim 裝屌指南 • EP III: Debug 裝屌指南
  • 108. 講完惹 關愛 Swift 發展者或想討論 ,歡迎和我聯聯繫 tjazzterATgmailDOTcom