@@ -930,7 +930,7 @@ namespace ts {
930
930
return isBinaryOperator ( node . kind ) ;
931
931
}
932
932
933
- type BinaryExpressionState = < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , resultHolder : { value : TResult } ) => number ;
933
+ type BinaryExpressionState = < TOuterState , TState , TResult > ( machine : BinaryExpressionStateMachine < TOuterState , TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , resultHolder : { value : TResult } , outerState : TOuterState ) => number ;
934
934
935
935
namespace BinaryExpressionState {
936
936
/**
@@ -939,10 +939,10 @@ namespace ts {
939
939
* @param frame The current frame
940
940
* @returns The new frame
941
941
*/
942
- export function enter < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , _resultHolder : { value : TResult } ) : number {
942
+ export function enter < TOuterState , TState , TResult > ( machine : BinaryExpressionStateMachine < TOuterState , TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , _resultHolder : { value : TResult } , outerState : TOuterState ) : number {
943
943
const prevUserState = stackIndex > 0 ? userStateStack [ stackIndex - 1 ] : undefined ;
944
944
Debug . assertEqual ( stateStack [ stackIndex ] , enter ) ;
945
- userStateStack [ stackIndex ] = machine . onEnter ( nodeStack [ stackIndex ] , prevUserState ) ;
945
+ userStateStack [ stackIndex ] = machine . onEnter ( nodeStack [ stackIndex ] , prevUserState , outerState ) ;
946
946
stateStack [ stackIndex ] = nextState ( machine , enter ) ;
947
947
return stackIndex ;
948
948
}
@@ -953,7 +953,7 @@ namespace ts {
953
953
* @param frame The current frame
954
954
* @returns The new frame
955
955
*/
956
- export function left < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , _resultHolder : { value : TResult } ) : number {
956
+ export function left < TOuterState , TState , TResult > ( machine : BinaryExpressionStateMachine < TOuterState , TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , _resultHolder : { value : TResult } , _outerState : TOuterState ) : number {
957
957
Debug . assertEqual ( stateStack [ stackIndex ] , left ) ;
958
958
Debug . assertIsDefined ( machine . onLeft ) ;
959
959
stateStack [ stackIndex ] = nextState ( machine , left ) ;
@@ -971,7 +971,7 @@ namespace ts {
971
971
* @param frame The current frame
972
972
* @returns The new frame
973
973
*/
974
- export function operator < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , _resultHolder : { value : TResult } ) : number {
974
+ export function operator < TOuterState , TState , TResult > ( machine : BinaryExpressionStateMachine < TOuterState , TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , _resultHolder : { value : TResult } , _outerState : TOuterState ) : number {
975
975
Debug . assertEqual ( stateStack [ stackIndex ] , operator ) ;
976
976
Debug . assertIsDefined ( machine . onOperator ) ;
977
977
stateStack [ stackIndex ] = nextState ( machine , operator ) ;
@@ -985,7 +985,7 @@ namespace ts {
985
985
* @param frame The current frame
986
986
* @returns The new frame
987
987
*/
988
- export function right < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , _resultHolder : { value : TResult } ) : number {
988
+ export function right < TOuterState , TState , TResult > ( machine : BinaryExpressionStateMachine < TOuterState , TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , _resultHolder : { value : TResult } , _outerState : TOuterState ) : number {
989
989
Debug . assertEqual ( stateStack [ stackIndex ] , right ) ;
990
990
Debug . assertIsDefined ( machine . onRight ) ;
991
991
stateStack [ stackIndex ] = nextState ( machine , right ) ;
@@ -1003,7 +1003,7 @@ namespace ts {
1003
1003
* @param frame The current frame
1004
1004
* @returns The new frame
1005
1005
*/
1006
- export function exit < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , resultHolder : { value : TResult } ) : number {
1006
+ export function exit < TOuterState , TState , TResult > ( machine : BinaryExpressionStateMachine < TOuterState , TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , resultHolder : { value : TResult } , _outerState : TOuterState ) : number {
1007
1007
Debug . assertEqual ( stateStack [ stackIndex ] , exit ) ;
1008
1008
stateStack [ stackIndex ] = nextState ( machine , exit ) ;
1009
1009
const result = machine . onExit ( nodeStack [ stackIndex ] , userStateStack [ stackIndex ] ) ;
@@ -1024,12 +1024,12 @@ namespace ts {
1024
1024
* Handles a frame that is already done.
1025
1025
* @returns The `done` state.
1026
1026
*/
1027
- export function done < TState , TResult > ( _machine : BinaryExpressionStateMachine < TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , _nodeStack : BinaryExpression [ ] , _userStateStack : TState [ ] , _resultHolder : { value : TResult } ) : number {
1027
+ export function done < TOuterState , TState , TResult > ( _machine : BinaryExpressionStateMachine < TOuterState , TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , _nodeStack : BinaryExpression [ ] , _userStateStack : TState [ ] , _resultHolder : { value : TResult } , _outerState : TOuterState ) : number {
1028
1028
Debug . assertEqual ( stateStack [ stackIndex ] , done ) ;
1029
1029
return stackIndex ;
1030
1030
}
1031
1031
1032
- export function nextState < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , currentState : BinaryExpressionState ) {
1032
+ export function nextState < TOuterState , TState , TResult > ( machine : BinaryExpressionStateMachine < TOuterState , TState , TResult > , currentState : BinaryExpressionState ) {
1033
1033
switch ( currentState ) {
1034
1034
case enter :
1035
1035
if ( machine . onLeft ) return left ;
@@ -1068,9 +1068,9 @@ namespace ts {
1068
1068
/**
1069
1069
* Holds state machine handler functions
1070
1070
*/
1071
- class BinaryExpressionStateMachine < TState , TResult > {
1071
+ class BinaryExpressionStateMachine < TOuterState , TState , TResult > {
1072
1072
constructor (
1073
- readonly onEnter : ( node : BinaryExpression , prev : TState | undefined ) => TState ,
1073
+ readonly onEnter : ( node : BinaryExpression , prev : TState | undefined , outerState : TOuterState ) => TState ,
1074
1074
readonly onLeft : ( ( left : Expression , userState : TState , node : BinaryExpression ) => BinaryExpression | void ) | undefined ,
1075
1075
readonly onOperator : ( ( operatorToken : BinaryOperatorToken , userState : TState , node : BinaryExpression ) => void ) | undefined ,
1076
1076
readonly onRight : ( ( right : Expression , userState : TState , node : BinaryExpression ) => BinaryExpression | void ) | undefined ,
@@ -1089,26 +1089,53 @@ namespace ts {
1089
1089
* @param foldState Callback evaluated when the result from a nested `onExit` should be folded into the state of that node's parent.
1090
1090
* @returns A function that walks a `BinaryExpression` node using the above callbacks, returning the result of the call to `onExit` from the outermost `BinaryExpression` node.
1091
1091
*/
1092
- export function createBinaryExpressionTrampoline < TState , TResult > (
1092
+ export function createBinaryExpressionTrampoline < TState , TResult > (
1093
1093
onEnter : ( node : BinaryExpression , prev : TState | undefined ) => TState ,
1094
1094
onLeft : ( ( left : Expression , userState : TState , node : BinaryExpression ) => BinaryExpression | void ) | undefined ,
1095
1095
onOperator : ( ( operatorToken : BinaryOperatorToken , userState : TState , node : BinaryExpression ) => void ) | undefined ,
1096
1096
onRight : ( ( right : Expression , userState : TState , node : BinaryExpression ) => BinaryExpression | void ) | undefined ,
1097
1097
onExit : ( node : BinaryExpression , userState : TState ) => TResult ,
1098
1098
foldState : ( ( userState : TState , result : TResult , side : "left" | "right" ) => TState ) | undefined ,
1099
+ ) : ( node : BinaryExpression ) => TResult ;
1100
+ /**
1101
+ * Creates a state machine that walks a `BinaryExpression` using the heap to reduce call-stack depth on a large tree.
1102
+ * @param onEnter Callback evaluated when entering a `BinaryExpression`. Returns new user-defined state to associate with the node while walking.
1103
+ * @param onLeft Callback evaluated when walking the left side of a `BinaryExpression`. Return a `BinaryExpression` to continue walking, or `void` to advance to the right side.
1104
+ * @param onRight Callback evaluated when walking the right side of a `BinaryExpression`. Return a `BinaryExpression` to continue walking, or `void` to advance to the end of the node.
1105
+ * @param onExit Callback evaluated when exiting a `BinaryExpression`. The result returned will either be folded into the parent's state, or returned from the walker if at the top frame.
1106
+ * @param foldState Callback evaluated when the result from a nested `onExit` should be folded into the state of that node's parent.
1107
+ * @returns A function that walks a `BinaryExpression` node using the above callbacks, returning the result of the call to `onExit` from the outermost `BinaryExpression` node.
1108
+ */
1109
+ export function createBinaryExpressionTrampoline < TOuterState , TState , TResult > (
1110
+ onEnter : ( node : BinaryExpression , prev : TState | undefined , outerState : TOuterState ) => TState ,
1111
+ onLeft : ( ( left : Expression , userState : TState , node : BinaryExpression ) => BinaryExpression | void ) | undefined ,
1112
+ onOperator : ( ( operatorToken : BinaryOperatorToken , userState : TState , node : BinaryExpression ) => void ) | undefined ,
1113
+ onRight : ( ( right : Expression , userState : TState , node : BinaryExpression ) => BinaryExpression | void ) | undefined ,
1114
+ onExit : ( node : BinaryExpression , userState : TState ) => TResult ,
1115
+ foldState : ( ( userState : TState , result : TResult , side : "left" | "right" ) => TState ) | undefined ,
1116
+ ) : ( node : BinaryExpression , outerState : TOuterState ) => TResult ;
1117
+ export function createBinaryExpressionTrampoline < TOuterState , TState , TResult > (
1118
+ onEnter : ( node : BinaryExpression , prev : TState | undefined , outerState : TOuterState ) => TState ,
1119
+ onLeft : ( ( left : Expression , userState : TState , node : BinaryExpression ) => BinaryExpression | void ) | undefined ,
1120
+ onOperator : ( ( operatorToken : BinaryOperatorToken , userState : TState , node : BinaryExpression ) => void ) | undefined ,
1121
+ onRight : ( ( right : Expression , userState : TState , node : BinaryExpression ) => BinaryExpression | void ) | undefined ,
1122
+ onExit : ( node : BinaryExpression , userState : TState ) => TResult ,
1123
+ foldState : ( ( userState : TState , result : TResult , side : "left" | "right" ) => TState ) | undefined ,
1099
1124
) {
1100
1125
const machine = new BinaryExpressionStateMachine ( onEnter , onLeft , onOperator , onRight , onExit , foldState ) ;
1101
- return ( node : BinaryExpression ) => {
1126
+ return trampoline ;
1127
+
1128
+ function trampoline ( node : BinaryExpression , outerState ?: TOuterState ) {
1102
1129
const resultHolder : { value : TResult } = { value : undefined ! } ;
1103
1130
const stateStack : BinaryExpressionState [ ] = [ BinaryExpressionState . enter ] ;
1104
1131
const nodeStack : BinaryExpression [ ] = [ node ] ;
1105
1132
const userStateStack : TState [ ] = [ undefined ! ] ;
1106
1133
let stackIndex = 0 ;
1107
1134
while ( stateStack [ stackIndex ] !== BinaryExpressionState . done ) {
1108
- stackIndex = stateStack [ stackIndex ] ( machine , stackIndex , stateStack , nodeStack , userStateStack , resultHolder ) ;
1135
+ stackIndex = stateStack [ stackIndex ] ( machine , stackIndex , stateStack , nodeStack , userStateStack , resultHolder , outerState ) ;
1109
1136
}
1110
1137
Debug . assertEqual ( stackIndex , 0 ) ;
1111
1138
return resultHolder . value ;
1112
- } ;
1139
+ }
1113
1140
}
1114
1141
}
0 commit comments