@@ -49,6 +49,8 @@ import {
4949 ConsoleStatementNode ,
5050 SliceNode ,
5151 DoWhileNode ,
52+ WhileNode ,
53+ ForNode ,
5254} from '../ast/AST.js' ;
5355import AstTraversal from '../ast/AstTraversal.js' ;
5456import { GlobalFunction , Class } from '../ast/Globals.js' ;
@@ -450,6 +452,69 @@ export default class GenerateTargetTraversalWithLocation extends AstTraversal {
450452 return node ;
451453 }
452454
455+ visitWhile ( node : WhileNode ) : Node {
456+ this . scopeDepth += 1 ;
457+ this . emit ( Op . OP_BEGIN , { location : node . location , positionHint : PositionHint . START } ) ;
458+
459+ node . condition = this . visit ( node . condition ) ;
460+ this . emit ( Op . OP_DUP , { location : node . condition . location , positionHint : PositionHint . END } ) ;
461+ this . pushToStack ( '(value)' ) ;
462+ this . emit ( Op . OP_TOALTSTACK , { location : node . condition . location , positionHint : PositionHint . END } ) ;
463+ this . popFromStack ( ) ;
464+
465+ this . popFromStack ( ) ;
466+ this . emit ( Op . OP_IF , { location : node . block . location , positionHint : PositionHint . START } ) ;
467+
468+ const bodyStackDepth = this . stack . length ;
469+ node . block = this . visit ( node . block ) as BlockNode ;
470+ this . removeScopedVariables ( bodyStackDepth , node . block ) ;
471+
472+ this . emit ( Op . OP_ENDIF , { location : node . block . location , positionHint : PositionHint . END } ) ;
473+ this . emit ( Op . OP_FROMALTSTACK , { location : node . block . location , positionHint : PositionHint . END } ) ;
474+ this . pushToStack ( '(value)' ) ;
475+ this . emit ( Op . OP_NOT , { location : node . location , positionHint : PositionHint . END } ) ;
476+ this . emit ( Op . OP_UNTIL , { location : node . location , positionHint : PositionHint . END } ) ;
477+ this . popFromStack ( ) ;
478+
479+ this . scopeDepth -= 1 ;
480+
481+ return node ;
482+ }
483+
484+ visitFor ( node : ForNode ) : Node {
485+ const forScopeStackDepth = this . stack . length ;
486+ node . init = this . visit ( node . init ) as VariableDefinitionNode | AssignNode ;
487+
488+ this . scopeDepth += 1 ;
489+ this . emit ( Op . OP_BEGIN , { location : node . location , positionHint : PositionHint . START } ) ;
490+
491+ node . condition = this . visit ( node . condition ) ;
492+ this . emit ( Op . OP_DUP , { location : node . condition . location , positionHint : PositionHint . END } ) ;
493+ this . pushToStack ( '(value)' ) ;
494+ this . emit ( Op . OP_TOALTSTACK , { location : node . condition . location , positionHint : PositionHint . END } ) ;
495+ this . popFromStack ( ) ;
496+
497+ this . popFromStack ( ) ;
498+ this . emit ( Op . OP_IF , { location : node . block . location , positionHint : PositionHint . START } ) ;
499+
500+ const bodyStackDepth = this . stack . length ;
501+ node . block = this . visit ( node . block ) as BlockNode ;
502+ node . update = this . visit ( node . update ) as AssignNode ;
503+ this . removeScopedVariables ( bodyStackDepth , node . block ) ;
504+
505+ this . emit ( Op . OP_ENDIF , { location : node . block . location , positionHint : PositionHint . END } ) ;
506+ this . emit ( Op . OP_FROMALTSTACK , { location : node . block . location , positionHint : PositionHint . END } ) ;
507+ this . pushToStack ( '(value)' ) ;
508+ this . emit ( Op . OP_NOT , { location : node . location , positionHint : PositionHint . END } ) ;
509+ this . emit ( Op . OP_UNTIL , { location : node . location , positionHint : PositionHint . END } ) ;
510+ this . popFromStack ( ) ;
511+
512+ this . scopeDepth -= 1 ;
513+ this . removeScopedVariables ( forScopeStackDepth , node ) ;
514+
515+ return node ;
516+ }
517+
453518 removeScopedVariables ( depthBeforeScope : number , node : Node ) : void {
454519 const dropCount = this . stack . length - depthBeforeScope ;
455520 for ( let i = 0 ; i < dropCount ; i += 1 ) {
0 commit comments