Пример #1
0
 void ASTVisitor.Accept(NodeWhile value)
 {
     Accept(value);
 }
Пример #2
0
        internal void Accept(NodeWhile expr)
        {
            var isResultRequired = expr.isResultRequired;
            var hasEl = expr.fail != null;

            var condition = expr.condition;

            uint initFailLoc = 0, initPassLoc = 0, start, failLoc;

            // Disable scopes, we'll do them ourselves
            if (expr.pass is NodeBlock)
                (expr.pass as NodeBlock).createScope = false;
            if (expr.fail != null && expr.fail is NodeBlock)
                (expr.fail as NodeBlock).createScope = false;

            expr.pass.isResultRequired = isResultRequired;
            expr.pass.inTailPosition = expr.inTailPosition;

            builder.StartScope();
            if (hasEl)
            {
                expr.fail.isResultRequired = isResultRequired;
                expr.fail.inTailPosition = expr.inTailPosition;

                // initial if
                condition.Visit(this);
                initFailLoc = builder.InsnCount;
                if (expr.not)
                    builder.OpJumpT(0);
                else builder.OpJumpF(0);
            }

            // while loop
            if (isResultRequired)
                builder.OpList(0);

            if (hasEl)
                initPassLoc = builder.OpJump(0);

            //*/ Handle cont
            if (isResultRequired)
                builder.OpJump(builder.InsnCount + 2);
            builder.StartFlowBlock(expr.label);
            if (isResultRequired)
                builder.OpPop(false);
            // END Handle cont */

            start = builder.InsnCount;
            {
                condition.Visit(this);
                failLoc = builder.InsnCount;
                if (expr.not)
                    builder.OpJumpT(0);
                else builder.OpJumpF(0);
            }

            if (hasEl)
                builder.SetOpC(initPassLoc, builder.InsnCount);
            if (isResultRequired)
                builder.OpDup();
            expr.pass.Visit(this);
            if (isResultRequired)
            {
                builder.OpOIStore("+");
                builder.OpPop();
            }
            builder.OpJump(start);

            //*/ Handle break
            if (isResultRequired)
                builder.OpJump(builder.InsnCount + 2);
            builder.EndFlowBlock();
            if (isResultRequired)
                builder.OpPop(false);
            // END Handle break */
            builder.EndScope();
            builder.SetOpC(failLoc, builder.InsnCount);
            uint finalFailLoc = builder.OpJump(0);

            // el
            if (hasEl)
            {
                builder.SetOpC(initFailLoc, builder.InsnCount);
                builder.StartScope();
                expr.fail.Visit(this);
                builder.EndScope();
            }

            builder.SetOpC(finalFailLoc, builder.InsnCount);
        }
Пример #3
0
        private Node ParseWhile()
        {
            var expr = new NodeWhile(Location);
            Advance();

            // while not (condition) is allowed and handled specially.
            if (Check(NOT))
            {
                expr.not = true;
                Advance();
            }

            if (Check(COLON))
            {
                Advance();
                ExpectIdentifier(out expr.label, "Expected an identifier for loop label.");
            }

            // Conditions must be in braces ()
            Expect(OPEN_BRACE, "An open brace ('(') is expected to start the condition of a 'while' expression.");
            if (!TokensRemain)
            {
                log.Error(expr.location, "Expected expression for 'while' condition, but the end of the file was reached.");
                return expr;
            }
            expr.condition = Expression();
            Expect(CLOSE_BRACE, "A close brace (')') is expected to end the condition of a 'while' expression.");

            // Get the body:
            if (!TokensRemain)
            {
                log.Error(expr.location, "Expected expression for 'while' block, but the end of the file was reached.");
                return expr;
            }
            expr.pass = Expression();

            // Check for an 'el' (fail) condition
            if (Check(EL))
            {
                Advance();
                expr.fail = Expression();
            }

            return expr;
        }