@@ -930,7 +930,7 @@ namespace ts {
930930 return isBinaryOperator ( node . kind ) ;
931931 }
932932
933- type BinaryExpressionState = < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , frame : BinaryExpressionStateMachineFrame < TState , TResult > ) => BinaryExpressionStateMachineFrame < TState , TResult > ;
933+ type BinaryExpressionState = < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , resultHolder : { value : TResult } ) => number ;
934934
935935 namespace BinaryExpressionState {
936936 /**
@@ -939,11 +939,12 @@ namespace ts {
939939 * @param frame The current frame
940940 * @returns The new frame
941941 */
942- export function enter < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , frame : BinaryExpressionStateMachineFrame < TState , TResult > ) : BinaryExpressionStateMachineFrame < TState , TResult > {
943- Debug . assertEqual ( frame . state , enter ) ;
944- frame . userState = machine . onEnter ( frame . node , frame . prev ?. userState ) ;
945- frame . state = nextState ( machine , enter ) ;
946- return frame ;
942+ export function enter < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , _resultHolder : { value : TResult } ) : number {
943+ const prevUserState = stackIndex > 0 ? userStateStack [ stackIndex - 1 ] : undefined ;
944+ Debug . assertEqual ( stateStack [ stackIndex ] , enter ) ;
945+ userStateStack [ stackIndex ] = machine . onEnter ( nodeStack [ stackIndex ] , prevUserState ) ;
946+ stateStack [ stackIndex ] = nextState ( machine , enter ) ;
947+ return stackIndex ;
947948 }
948949
949950 /**
@@ -952,16 +953,16 @@ namespace ts {
952953 * @param frame The current frame
953954 * @returns The new frame
954955 */
955- export function left < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , frame : BinaryExpressionStateMachineFrame < TState , TResult > ) : BinaryExpressionStateMachineFrame < TState , TResult > {
956- Debug . assertEqual ( frame . state , left ) ;
956+ export function left < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , _resultHolder : { value : TResult } ) : number {
957+ Debug . assertEqual ( stateStack [ stackIndex ] , left ) ;
957958 Debug . assertIsDefined ( machine . onLeft ) ;
958- frame . state = nextState ( machine , left ) ;
959- const nextNode = machine . onLeft ( frame . node . left , frame . userState , frame . node ) ;
959+ stateStack [ stackIndex ] = nextState ( machine , left ) ;
960+ const nextNode = machine . onLeft ( nodeStack [ stackIndex ] . left , userStateStack [ stackIndex ] , nodeStack [ stackIndex ] ) ;
960961 if ( nextNode ) {
961- checkCircularity ( frame , nextNode ) ;
962- return new BinaryExpressionStateMachineFrame ( frame , nextNode ) ;
962+ checkCircularity ( stackIndex , nodeStack , nextNode ) ;
963+ return pushStack ( stackIndex , stateStack , nodeStack , userStateStack , nextNode ) ;
963964 }
964- return frame ;
965+ return stackIndex ;
965966 }
966967
967968 /**
@@ -970,12 +971,12 @@ namespace ts {
970971 * @param frame The current frame
971972 * @returns The new frame
972973 */
973- export function operator < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , frame : BinaryExpressionStateMachineFrame < TState , TResult > ) : BinaryExpressionStateMachineFrame < TState , TResult > {
974- Debug . assertEqual ( frame . state , operator ) ;
974+ export function operator < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , _resultHolder : { value : TResult } ) : number {
975+ Debug . assertEqual ( stateStack [ stackIndex ] , operator ) ;
975976 Debug . assertIsDefined ( machine . onOperator ) ;
976- frame . state = nextState ( machine , operator ) ;
977- machine . onOperator ( frame . node . operatorToken , frame . userState , frame . node ) ;
978- return frame ;
977+ stateStack [ stackIndex ] = nextState ( machine , operator ) ;
978+ machine . onOperator ( nodeStack [ stackIndex ] . operatorToken , userStateStack [ stackIndex ] , nodeStack [ stackIndex ] ) ;
979+ return stackIndex ;
979980 }
980981
981982 /**
@@ -984,16 +985,16 @@ namespace ts {
984985 * @param frame The current frame
985986 * @returns The new frame
986987 */
987- export function right < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , frame : BinaryExpressionStateMachineFrame < TState , TResult > ) : BinaryExpressionStateMachineFrame < TState , TResult > {
988- Debug . assertEqual ( frame . state , right ) ;
988+ export function right < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , _resultHolder : { value : TResult } ) : number {
989+ Debug . assertEqual ( stateStack [ stackIndex ] , right ) ;
989990 Debug . assertIsDefined ( machine . onRight ) ;
990- frame . state = nextState ( machine , right ) ;
991- const nextNode = machine . onRight ( frame . node . right , frame . userState , frame . node ) ;
991+ stateStack [ stackIndex ] = nextState ( machine , right ) ;
992+ const nextNode = machine . onRight ( nodeStack [ stackIndex ] . right , userStateStack [ stackIndex ] , nodeStack [ stackIndex ] ) ;
992993 if ( nextNode ) {
993- checkCircularity ( frame , nextNode ) ;
994- return new BinaryExpressionStateMachineFrame ( frame , nextNode ) ;
994+ checkCircularity ( stackIndex , nodeStack , nextNode ) ;
995+ return pushStack ( stackIndex , stateStack , nodeStack , userStateStack , nextNode ) ;
995996 }
996- return frame ;
997+ return stackIndex ;
997998 }
998999
9991000 /**
@@ -1002,25 +1003,28 @@ namespace ts {
10021003 * @param frame The current frame
10031004 * @returns The new frame
10041005 */
1005- export function exit < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , frame : BinaryExpressionStateMachineFrame < TState , TResult > ) : BinaryExpressionStateMachineFrame < TState , TResult > {
1006- Debug . assertEqual ( frame . state , exit ) ;
1007- frame . state = nextState ( machine , exit ) ;
1008- frame . result = machine . onExit ( frame . node , frame . userState ) ;
1009- if ( frame . prev ) {
1010- const side = frame . prev . state === exit ? "right" : "left" ;
1011- frame . prev . userState = machine . foldState ( frame . prev . userState , frame . result , side ) ;
1012- return frame . prev ;
1006+ export function exit < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , resultHolder : { value : TResult } ) : number {
1007+ Debug . assertEqual ( stateStack [ stackIndex ] , exit ) ;
1008+ stateStack [ stackIndex ] = nextState ( machine , exit ) ;
1009+ const result = machine . onExit ( nodeStack [ stackIndex ] , userStateStack [ stackIndex ] ) ;
1010+ if ( stackIndex > 0 ) {
1011+ stackIndex -- ;
1012+ const side = stateStack [ stackIndex ] === exit ? "right" : "left" ;
1013+ userStateStack [ stackIndex ] = machine . foldState ( userStateStack [ stackIndex ] , result , side ) ;
10131014 }
1014- return frame ;
1015+ else {
1016+ resultHolder . value = result ;
1017+ }
1018+ return stackIndex ;
10151019 }
10161020
10171021 /**
10181022 * Handles a frame that is already done.
10191023 * @returns The `done` state.
10201024 */
1021- export function done < TState , TResult > ( _machine : BinaryExpressionStateMachine < TState , TResult > , frame : BinaryExpressionStateMachineFrame < TState , TResult > ) : BinaryExpressionStateMachineFrame < TState , TResult > {
1022- Debug . assertEqual ( frame . state , done ) ;
1023- return frame ;
1025+ export function done < TState , TResult > ( _machine : BinaryExpressionStateMachine < TState , TResult > , stackIndex : number , stateStack : BinaryExpressionState [ ] , _nodeStack : BinaryExpression [ ] , _userStateStack : TState [ ] , _resultHolder : { value : TResult } ) : number {
1026+ Debug . assertEqual ( stateStack [ stackIndex ] , done ) ;
1027+ return stackIndex ;
10241028 }
10251029
10261030 export function nextState < TState , TResult > ( machine : BinaryExpressionStateMachine < TState , TResult > , currentState : BinaryExpressionState ) {
@@ -1041,11 +1045,19 @@ namespace ts {
10411045 }
10421046 }
10431047
1044- function checkCircularity < TState , TResult > ( frame : BinaryExpressionStateMachineFrame < TState , TResult > | undefined , node : BinaryExpression ) {
1048+ function pushStack < TState > ( stackIndex : number , stateStack : BinaryExpressionState [ ] , nodeStack : BinaryExpression [ ] , userStateStack : TState [ ] , node : BinaryExpression ) {
1049+ stackIndex ++ ;
1050+ stateStack [ stackIndex ] = BinaryExpressionState . enter ;
1051+ nodeStack [ stackIndex ] = node ;
1052+ userStateStack [ stackIndex ] = undefined ! ;
1053+ return stackIndex ;
1054+ }
1055+
1056+ function checkCircularity ( stackIndex : number , nodeStack : BinaryExpression [ ] , node : BinaryExpression ) {
10451057 if ( Debug . shouldAssert ( AssertionLevel . Aggressive ) ) {
1046- while ( frame ) {
1047- Debug . assert ( frame . node !== node , "Circular traversal detected." ) ;
1048- frame = frame . prev ;
1058+ while ( stackIndex >= 0 ) {
1059+ Debug . assert ( nodeStack [ stackIndex ] !== node , "Circular traversal detected." ) ;
1060+ stackIndex -- ;
10491061 }
10501062 }
10511063 }
@@ -1066,20 +1078,6 @@ namespace ts {
10661078 }
10671079 }
10681080
1069- /**
1070- * Holds the current frame for the state machine
1071- */
1072- class BinaryExpressionStateMachineFrame < TState , TResult > {
1073- public state : BinaryExpressionState = BinaryExpressionState . enter ;
1074- public userState : TState = undefined ! ;
1075- public result : TResult = undefined ! ;
1076- constructor (
1077- public prev : BinaryExpressionStateMachineFrame < TState , TResult > | undefined ,
1078- public node : BinaryExpression
1079- ) {
1080- }
1081- }
1082-
10831081 /**
10841082 * Creates a state machine that walks a `BinaryExpression` using the heap to reduce call-stack depth on a large tree.
10851083 * @param onEnter Callback evaluated when entering a `BinaryExpression`. Returns new user-defined state to associate with the node while walking.
@@ -1089,7 +1087,7 @@ namespace ts {
10891087 * @param foldState Callback evaluated when the result from a nested `onExit` should be folded into the state of that node's parent.
10901088 * @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.
10911089 */
1092- export function createBinaryExpressionWalker < TState , TResult > (
1090+ export function createBinaryExpressionTrampoline < TState , TResult > (
10931091 onEnter : ( node : BinaryExpression , prev : TState | undefined ) => TState ,
10941092 onLeft : ( ( left : Expression , userState : TState , node : BinaryExpression ) => BinaryExpression | void ) | undefined ,
10951093 onOperator : ( ( operatorToken : BinaryOperatorToken , userState : TState , node : BinaryExpression ) => void ) | undefined ,
@@ -1099,11 +1097,16 @@ namespace ts {
10991097 ) {
11001098 const machine = new BinaryExpressionStateMachine ( onEnter , onLeft , onOperator , onRight , onExit , foldState ) ;
11011099 return ( node : BinaryExpression ) => {
1102- let frame = new BinaryExpressionStateMachineFrame < TState , TResult > ( /*prev*/ undefined , node ) ;
1103- while ( frame . state !== BinaryExpressionState . done ) {
1104- frame = frame . state ( machine , frame ) ;
1100+ const resultHolder : { value : TResult } = { value : undefined ! } ;
1101+ const stateStack : BinaryExpressionState [ ] = [ BinaryExpressionState . enter ] ;
1102+ const nodeStack : BinaryExpression [ ] = [ node ] ;
1103+ const userStateStack : TState [ ] = [ undefined ! ] ;
1104+ let stackIndex = 0 ;
1105+ while ( stateStack [ stackIndex ] !== BinaryExpressionState . done ) {
1106+ stackIndex = stateStack [ stackIndex ] ( machine , stackIndex , stateStack , nodeStack , userStateStack , resultHolder ) ;
11051107 }
1106- return frame . result ;
1108+ Debug . assertEqual ( stackIndex , 0 ) ;
1109+ return resultHolder . value ;
11071110 } ;
11081111 }
11091112}
0 commit comments