docs: clang 插件开发

This commit is contained in:
杭城小刘
2024-04-27 13:01:58 +08:00
parent 6e47061735
commit 851797d133
257 changed files with 9060 additions and 239 deletions

142
Chapter1 - iOS/1.123.md Normal file
View File

@@ -0,0 +1,142 @@
# Swift 模式匹配
## 模式匹配的底层实现
为了去除其他语句对汇编研究造成的干扰,所以 case 和 default 里面都很简单,聚焦于研究 case 的模式匹配实现。测试代码如下:
```swift
var age = 28
switch age {
case 0...30:
break
default:
break
}
```
`case 0...30:` 处加断点可以看到汇编,然后看到可疑方法 `Swift.RangeExpression.~= infix(τ_0_0, τ_0_0.Bound) -> Swift.Bool`
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/SwiftPatternMatchExplore.png" style="zoom:25%">
LLDB 输入 `si` 进去窥探下
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/SwiftPatternMatchExplore2.png" style="zoom:25%">
看样子,函数还没到底,看到地址 `0x00007ff81a86f530` 很大很大,猜测应该是一个系统动态库方法地址,继续跟进去研究 `si`
![](https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/MemoryLayout.png)
可以看到内部还有函数调用
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/SwiftPatternMatchExplore3.png" style="zoom:25%">
继续跟进 `si`
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/SwiftPatternMatchExplore4.png" style="zoom:25%">
看上去是在做继续 `clasedRange` 区间符合的判断,继续跟进 `si`,里面确实是在判断是否命中区间的判断。不一一研究了,这次目的是判断 switch...case pattern 的实现。
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/SwiftPatternMatchExplore5.png" style="zoom:25%">
结论switch case pattern 模式匹配,系统底层实现是依赖
## 模式匹配的应用
自定义模式匹配。根据上面通过汇编进行分析,我们知道
- `static func ~=(pattern: case 后面的值, value: switch 后面的值)` pattern 代表的是 case 后面的值value 代表 switch 后面的值。
- 当 case 有不同类型的时候,如果编译报错,则需要重写 `static func ~=(pattern: ,value: )` 方法,调整 pattern 的数据类型,数据类型应该和 case 后的数据类型一致(可以是函数等)
```swift
struct Student {
var score = 0
var name = ""
/// Student Int
/// - Parameters:
/// - pattern: case
/// - value: switch
/// - Returns:
static func ~= (pattern: Int, value: Student) -> Bool {
value.score >= pattern
}
static func ~= (pattern: Range<Int>, value: Student) -> Bool {
pattern.contains(value.score)
}
static func ~= (pattern: ClosedRange<Int>, value: Student) -> Bool {
pattern.contains(value.score)
}
static func ~= (pattern: String, value: Student) -> Bool {
Int(pattern) == value.score
}
}
var student: Student = Student(score: 55, name: "杭城小刘")
switch student {
case 100:
print(">=100")
case 90:
print(">=90")
case 80..<90:
print("[80, 90)")
case 60...79:
print("[60, 79]")
case "55":
print("斯国一")
default:
print("just so so")
}
// console
```
修改 `var student: Student = Student(score: 78, name: "杭城小刘")` 则输出 `[60, 79]`
```swift
extension String {
static func ~=(pattern: (String) -> Bool ,value: String) -> Bool {
pattern(value)
}
}
func hasPrefix(_ prefix: String) -> (String) -> Bool {
{$0.hasPrefix(prefix)}
}
func hasSuffix(_ prefix: String) -> (String) -> Bool {
{$0.hasSuffix(prefix)}
}
var name = "城小刘"
switch name {
case hasPrefix(""):
print("有杭哦")
case hasSuffix(""):
print("有刘哦")
default:
print("just a name")
}
// console
```
##