@@ -930,7 +930,7 @@ namespace ts {
930930 return isBinaryOperator ( node . kind ) ;
931931 }
932932
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 ;
934934
935935 namespace BinaryExpressionState {
936936 /**
@@ -939,10 +939,10 @@ namespace ts {
939939 * @param frame The current frame
940940 * @returns The new frame
941941 */
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 {
943943 const prevUserState = stackIndex > 0 ? userStateStack [ stackIndex - 1 ] : undefined ;
944944 Debug . assertEqual ( stateStack [ stackIndex ] , enter ) ;
945- userStateStack [ stackIndex ] = machine . onEnter ( nodeStack [ stackIndex ] , prevUserState ) ;
945+ userStateStack [ stackIndex ] = machine . onEnter ( nodeStack [ stackIndex ] , prevUserState , outerState ) ;
946946 stateStack [ stackIndex ] = nextState ( machine , enter ) ;
947947 return stackIndex ;
948948 }
@@ -953,7 +953,7 @@ namespace ts {
953953 * @param frame The current frame
954954 * @returns The new frame
955955 */
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 {
957957 Debug . assertEqual ( stateStack [ stackIndex ] , left ) ;
958958 Debug . assertIsDefined ( machine . onLeft ) ;
959959 stateStack [ stackIndex ] = nextState ( machine , left ) ;
@@ -971,7 +971,7 @@ namespace ts {
971971 * @param frame The current frame
972972 * @returns The new frame
973973 */
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 {
975975 Debug . assertEqual ( stateStack [ stackIndex ] , operator ) ;
976976 Debug . assertIsDefined ( machine . onOperator ) ;
977977 stateStack [ stackIndex ] = nextState ( machine , operator ) ;
@@ -985,7 +985,7 @@ namespace ts {
985985 * @param frame The current frame
986986 * @returns The new frame
987987 */
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 {
989989 Debug . assertEqual ( stateStack [ stackIndex ] , right ) ;
990990 Debug . assertIsDefined ( machine . onRight ) ;
991991 stateStack [ stackIndex ] = nextState ( machine , right ) ;
@@ -1003,7 +1003,7 @@ namespace ts {
10031003 * @param frame The current frame
10041004 * @returns The new frame
10051005 */
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 {
10071007 Debug . assertEqual ( stateStack [ stackIndex ] , exit ) ;
10081008 stateStack [ stackIndex ] = nextState ( machine , exit ) ;
10091009 const result = machine . onExit ( nodeStack [ stackIndex ] , userStateStack [ stackIndex ] ) ;
@@ -1024,12 +1024,12 @@ namespace ts {
10241024 * Handles a frame that is already done.
10251025 * @returns The `done` state.
10261026 */
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 {
10281028 Debug . assertEqual ( stateStack [ stackIndex ] , done ) ;
10291029 return stackIndex ;
10301030 }
10311031
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 ) {
10331033 switch ( currentState ) {
10341034 case enter :
10351035 if ( machine . onLeft ) return left ;
@@ -1068,9 +1068,9 @@ namespace ts {
10681068 /**
10691069 * Holds state machine handler functions
10701070 */
1071- class BinaryExpressionStateMachine < TState , TResult > {
1071+ class BinaryExpressionStateMachine < TOuterState , TState , TResult > {
10721072 constructor (
1073- readonly onEnter : ( node : BinaryExpression , prev : TState | undefined ) => TState ,
1073+ readonly onEnter : ( node : BinaryExpression , prev : TState | undefined , outerState : TOuterState ) => TState ,
10741074 readonly onLeft : ( ( left : Expression , userState : TState , node : BinaryExpression ) => BinaryExpression | void ) | undefined ,
10751075 readonly onOperator : ( ( operatorToken : BinaryOperatorToken , userState : TState , node : BinaryExpression ) => void ) | undefined ,
10761076 readonly onRight : ( ( right : Expression , userState : TState , node : BinaryExpression ) => BinaryExpression | void ) | undefined ,
@@ -1089,26 +1089,53 @@ namespace ts {
10891089 * @param foldState Callback evaluated when the result from a nested `onExit` should be folded into the state of that node's parent.
10901090 * @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.
10911091 */
1092- export function createBinaryExpressionTrampoline < TState , TResult > (
1092+ export function createBinaryExpressionTrampoline < TState , TResult > (
10931093 onEnter : ( node : BinaryExpression , prev : TState | undefined ) => TState ,
10941094 onLeft : ( ( left : Expression , userState : TState , node : BinaryExpression ) => BinaryExpression | void ) | undefined ,
10951095 onOperator : ( ( operatorToken : BinaryOperatorToken , userState : TState , node : BinaryExpression ) => void ) | undefined ,
10961096 onRight : ( ( right : Expression , userState : TState , node : BinaryExpression ) => BinaryExpression | void ) | undefined ,
10971097 onExit : ( node : BinaryExpression , userState : TState ) => TResult ,
10981098 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 ,
10991124 ) {
11001125 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 ) {
11021129 const resultHolder : { value : TResult } = { value : undefined ! } ;
11031130 const stateStack : BinaryExpressionState [ ] = [ BinaryExpressionState . enter ] ;
11041131 const nodeStack : BinaryExpression [ ] = [ node ] ;
11051132 const userStateStack : TState [ ] = [ undefined ! ] ;
11061133 let stackIndex = 0 ;
11071134 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 ) ;
11091136 }
11101137 Debug . assertEqual ( stackIndex , 0 ) ;
11111138 return resultHolder . value ;
1112- } ;
1139+ }
11131140 }
11141141}
0 commit comments