@@ -74,23 +74,19 @@ extension ProjectedValue {
74
74
/// The provided `visitor` can be used to override the handling a certain defs and uses during
75
75
/// the walk. See `EscapeVisitor` for details.
76
76
///
77
- func isEscaping( using visitor: some EscapeVisitor = DefaultVisitor ( ) ,
78
- complexityBudget: Int = Int . max,
79
- _ context: some Context ) -> Bool {
77
+ func isEscaping(
78
+ using visitor: some EscapeVisitor = DefaultVisitor ( ) ,
79
+ initialWalkingDirection: EscapeUtilityTypes . WalkingDirection = . up,
80
+ complexityBudget: Int = Int . max,
81
+ _ context: some Context
82
+ ) -> Bool {
80
83
var walker = EscapeWalker ( visitor: visitor, complexityBudget: complexityBudget, context)
81
- return walker. walkUp ( addressOrValue: value, path: path. escapePath) == . abortWalk
82
- }
83
-
84
- /// Returns true if the function argument escapes, but ignoring any potential escapes in the caller.
85
- ///
86
- /// This function is similar to `ProjectedValue.isEscaping()`, but it ignores any potential
87
- /// escapes which might have happened before the argument's function is called.
88
- /// Technically, this means that the walk starts downwards instead of upwards.
89
- ///
90
- func isEscapingWhenWalkingDown( using visitor: some EscapeVisitor = DefaultVisitor ( ) ,
91
- _ context: some Context ) -> Bool {
92
- var walker = EscapeWalker ( visitor: visitor, context)
93
- return walker. walkDown ( addressOrValue: value, path: path. escapePath) == . abortWalk
84
+ let result : WalkResult
85
+ switch initialWalkingDirection {
86
+ case . up: result = walker. walkUp ( addressOrValue: value, path: path. escapePath)
87
+ case . down: result = walker. walkDown ( addressOrValue: value, path: path. escapePath)
88
+ }
89
+ return result == . abortWalk
94
90
}
95
91
96
92
/// Returns the result of the visitor if the projected value does not escape.
@@ -99,27 +95,19 @@ extension ProjectedValue {
99
95
/// it returns the `result` of the `visitor`, if the projected value does not escape.
100
96
/// Returns nil, if the projected value escapes.
101
97
///
102
- func visit< V: EscapeVisitorWithResult > ( using visitor: V ,
103
- complexityBudget: Int = Int . max,
104
- _ context: some Context ) -> V . Result ? {
98
+ func visit< V: EscapeVisitorWithResult > (
99
+ using visitor: V ,
100
+ initialWalkingDirection: EscapeUtilityTypes . WalkingDirection = . up,
101
+ complexityBudget: Int = Int . max,
102
+ _ context: some Context
103
+ ) -> V . Result ? {
105
104
var walker = EscapeWalker ( visitor: visitor, complexityBudget: complexityBudget, context)
106
- if walker. walkUp ( addressOrValue: value, path: path. escapePath) == . abortWalk {
107
- walker. visitor. cleanupOnAbort ( )
108
- return nil
105
+ let result : WalkResult
106
+ switch initialWalkingDirection {
107
+ case . up: result = walker. walkUp ( addressOrValue: value, path: path. escapePath)
108
+ case . down: result = walker. walkDown ( addressOrValue: value, path: path. escapePath)
109
109
}
110
- return walker. visitor. result
111
- }
112
-
113
- /// Returns the result of the visitor if the projected value does not escape - ignoring
114
- /// any potential escapes in the caller.
115
- ///
116
- /// This function is similar to `isEscapingIgnoringCallerEscapes() -> Bool`, but instead
117
- /// of returning a Bool, it returns the `result` of the `visitor`.
118
- ///
119
- func visitByWalkingDown< V: EscapeVisitorWithResult > ( using visitor: V ,
120
- _ context: some Context ) -> V . Result ? {
121
- var walker = EscapeWalker ( visitor: visitor, context)
122
- if walker. walkDown ( addressOrValue: value, path: path. escapePath) == . abortWalk {
110
+ if result == . abortWalk {
123
111
walker. visitor. cleanupOnAbort ( )
124
112
return nil
125
113
}
@@ -129,19 +117,25 @@ extension ProjectedValue {
129
117
130
118
extension Value {
131
119
/// The un-projected version of `ProjectedValue.isEscaping()`.
132
- func isEscaping( using visitor : some EscapeVisitor = DefaultVisitor ( ) ,
133
- _ context : some Context ) -> Bool {
134
- return self . at ( SmallProjectionPath ( ) ) . isEscaping ( using : visitor , context )
135
- }
136
-
137
- func isEscapingWhenWalkingDown ( using visitor : some EscapeVisitor = DefaultVisitor ( ) ,
138
- _ context : some Context ) -> Bool {
139
- return self . at ( SmallProjectionPath ( ) ) . isEscapingWhenWalkingDown ( using : visitor , context)
120
+ func isEscaping(
121
+ using visitor : some EscapeVisitor = DefaultVisitor ( ) ,
122
+ initialWalkingDirection : EscapeUtilityTypes . WalkingDirection = . up ,
123
+ _ context : some Context
124
+ ) -> Bool {
125
+ return self . at ( SmallProjectionPath ( ) ) . isEscaping ( using : visitor ,
126
+ initialWalkingDirection : initialWalkingDirection ,
127
+ context)
140
128
}
141
129
142
130
/// The un-projected version of `ProjectedValue.visit()`.
143
- func visit< V: EscapeVisitorWithResult > ( using visitor: V , _ context: some Context ) -> V . Result ? {
144
- return self . at ( SmallProjectionPath ( ) ) . visit ( using: visitor, context)
131
+ func visit< V: EscapeVisitorWithResult > (
132
+ using visitor: V ,
133
+ initialWalkingDirection: EscapeUtilityTypes . WalkingDirection = . up,
134
+ _ context: some Context
135
+ ) -> V . Result ? {
136
+ return self . at ( SmallProjectionPath ( ) ) . visit ( using: visitor,
137
+ initialWalkingDirection: initialWalkingDirection,
138
+ context)
145
139
}
146
140
}
147
141
@@ -198,6 +192,11 @@ struct DefaultVisitor : EscapeVisitor {}
198
192
199
193
struct EscapeUtilityTypes {
200
194
195
+ enum WalkingDirection {
196
+ case up
197
+ case down
198
+ }
199
+
201
200
/// The EscapePath is updated and maintained during the up-walk and down-walk.
202
201
///
203
202
/// It's passed to the EscapeVisitor's `visitUse` and `visitDef`.
0 commit comments