Пример #1
0
        protected override BoundStatement RewriteIfStatement(BoundIfStatement node)
        {
            if (node.ElseStatement == null)
            {
                // if <condition>
                //     <then>
                //
                // ---->
                // gotoIfFalse <condition> end
                // <then>
                // end:

                var endLabel          = GenerateLabel();
                var gotoFalse         = new BoundConditionalGotoStatement(endLabel, node.Condition, false);
                var endLabelStatement = new BoundLabelStatement(endLabel);
                var result            = new BoundBlockStatement(ImmutableArray.Create(gotoFalse, node.ThenStatement, endLabelStatement));

                return(RewriteStatement(result));
            }
            else
            {
                // if <condition>
                //     <then>
                // else
                //     <else>
                //
                // ---->
                // gotoIfFalse <condition> else
                // <then>
                // goto end
                // else:
                // <else>
                // end:

                var elseLabel = GenerateLabel();
                var endLabel  = GenerateLabel();

                var gotoFalse          = new BoundConditionalGotoStatement(elseLabel, node.Condition, false);
                var gotoEndStatement   = new BoundGotoStatement(endLabel);
                var endLabelStatement  = new BoundLabelStatement(endLabel);
                var elseLabelStatement = new BoundLabelStatement(elseLabel);
                var result             = new BoundBlockStatement(ImmutableArray.Create(
                                                                     gotoFalse,
                                                                     node.ThenStatement,
                                                                     gotoEndStatement,
                                                                     elseLabelStatement,
                                                                     node.ElseStatement,
                                                                     endLabelStatement
                                                                     ));

                return(RewriteStatement(result));
            }
        }
Пример #2
0
        protected override BoundStatement RewriteDoWhileStatement(BoundDoWhileStatement node)
        {
            var continueLabelStmt = new BoundLabelStatement(node.ContinueLabel, node.IsValid);
            var breakLabelStmt    = new BoundLabelStatement(node.BreakLabel, node.IsValid);

            var gotoContinue = new BoundConditionalGotoStatement(node.ContinueLabel, node.Condition, jumpIfFalse: false, node.IsValid);

            var res = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(
                                                  continueLabelStmt,
                                                  node.Body,
                                                  gotoContinue,
                                                  breakLabelStmt
                                                  ), node.IsValid);

            return(RewriteStatement(res));
        }
Пример #3
0
        protected override BoundStatement RewriteIfStatement(BoundIfStatement node)
        {
            /*
             *  gotoIfFalse <condition> end
             *  <Then>
             *  end:
             *
             *  gotoIfFalse <condition> else
             *  <Then>
             *  goto end
             *  else:
             *  <Else>
             *  end:
             */

            BoundBlockStatement result;

            if (node.ElseClause is null)
            {
                result = Create();
            }
            else
            {
                result = CreateWithElse();
            }

            return(RewriteStatement(result));

            BoundBlockStatement Create()
            {
                var endLabelStatement    = new BoundLabelStatement(GenerateLabel());
                var gotoIfFalseStatement = new BoundConditionalGotoStatement(endLabelStatement.Label, node.Condition, false);

                return(new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(gotoIfFalseStatement, node.Statement, endLabelStatement)));
            }

            BoundBlockStatement CreateWithElse()
            {
                var elseLabelStatement   = new BoundLabelStatement(GenerateLabel());
                var endLabelStatement    = new BoundLabelStatement(GenerateLabel());
                var gotoIfFalseStatement = new BoundConditionalGotoStatement(elseLabelStatement.Label, node.Condition, false);
                var gotoEndStatement     = new BoundGotoStatement(endLabelStatement.Label);
                var statements           = ImmutableArray.Create <BoundStatement>(gotoIfFalseStatement, node.Statement, gotoEndStatement, elseLabelStatement, node.ElseClause, endLabelStatement);

                return(new BoundBlockStatement(statements));
            }
        }
Пример #4
0
        protected override BoundStatement RewriteConditionalGotoStatement(BoundConditionalGotoStatement node)
        {
            if (!(node.Condition.Constant is null) && node.Condition.Constant.Value is bool val)
            {
                val = node.JumpIfFalse ? !val : val;
                if (val)
                {
                    return(new BoundGotoStatement(node.Label, node.IsValid));
                }
                else
                {
                    return(new BoundNopStatement(node.IsValid));
                }
            }

            return(base.RewriteConditionalGotoStatement(node));
        }
Пример #5
0
        protected override BoundStatement RewriteConditionalGotoStatement(BoundConditionalGotoStatement node)
        {
            if (node.Condition.ConstantValue != null)
            {
                var condition = (bool)node.Condition.ConstantValue.Value;
                condition = node.JumpIfTrue ? condition : !condition;
                if (condition)
                {
                    return(RewriteStatement(Goto(node.Syntax, node.Label)));
                }
                else
                {
                    return(RewriteStatement(Nop(node.Syntax)));
                }
            }

            return(base.RewriteConditionalGotoStatement(node));
        }
Пример #6
0
        protected override BoundStatement RewriteWhileStatement(BoundWhileStatement node)
        {
            /*
             *  check:
             *  gotoIfFalse <condition> end
             *  <statement>
             *  goto check
             *  end:
             */

            var checkLabelStatement  = new BoundLabelStatement(GenerateLabel());
            var endLabelStatement    = new BoundLabelStatement(GenerateLabel());
            var gotoIfFalseStatement = new BoundConditionalGotoStatement(endLabelStatement.Label, node.Condition, false);
            var gotoCheckStatement   = new BoundGotoStatement(checkLabelStatement.Label);
            var statements           = ImmutableArray.Create <BoundStatement>(checkLabelStatement, gotoIfFalseStatement, node.Statement, gotoCheckStatement, endLabelStatement);
            var result = new BoundBlockStatement(statements);

            return(RewriteStatement(result));
        }
Пример #7
0
        protected override BoundStatement RewriteDoWhileStatement(BoundDoWhileStatement node)
        {
            var bodyLabel = GenerateLabel();

            var bodyLabelStatement     = new BoundLabelStatement(bodyLabel);
            var continueLabelStatement = new BoundLabelStatement(node.ContinueLabel);
            var gotoTrue            = new BoundConditionalGotoStatement(bodyLabel, node.Condition);
            var breakLabelStatement = new BoundLabelStatement(node.BreakLabel);

            var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(
                                                     bodyLabelStatement,
                                                     node.Body,
                                                     continueLabelStatement,
                                                     gotoTrue,
                                                     breakLabelStatement
                                                     ));

            return(RewriteStatement(result));
        }
Пример #8
0
    protected override BoundStatement RewriteBoundConditionalGotoStatement(
        BoundConditionalGotoStatement node
        )
    {
        var constant = ConstantFolding.Fold(node.Condition);

        if (constant == null)
        {
            return(base.RewriteBoundConditionalGotoStatement(node));
        }

        var condition  = (bool)constant.Value;
        var condition2 = node.JumpIfTrue ? condition : !condition;

        if (condition2)
        {
            return(new BoundGotoStatement(node.Syntax, node.BoundLabel));
        }

        return(new BoundNopStatement(node.Syntax));
    }
Пример #9
0
        protected override BoundStatement RewriteDoWhileStatement(BoundDoWhileStatement node)
        {
            BoundLabel bodyLabel = GenerateLabel();
            BoundLabel endLabel  = new BoundLabel("End");

            BoundLabelStatement           bodyLabelStatement     = new BoundLabelStatement(bodyLabel);
            BoundLabelStatement           continueLabelStatement = new BoundLabelStatement(node.ContinueLabel);
            BoundConditionalGotoStatement gotoTrue            = new BoundConditionalGotoStatement(bodyLabel, node.Condition, true);
            BoundLabelStatement           breakLabelStatement = new BoundLabelStatement(node.BreakLabel);
            BoundLabelStatement           endLabelStatement   = new BoundLabelStatement(endLabel);
            BoundBlockStatement           result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(
                                                                               bodyLabelStatement,
                                                                               node.Body,
                                                                               continueLabelStatement,
                                                                               gotoTrue,
                                                                               breakLabelStatement,
                                                                               endLabelStatement
                                                                               ));

            return(RewriteStatement(result));
        }
Пример #10
0
        protected override BoundStatement RewriteConditionalGotoStatement(BoundConditionalGotoStatement node)
        {
            var syntax = node.Syntax;

            if (node.Condition.ConstantValue != null)
            {
                var value     = (bool)node.Condition.ConstantValue.Value;
                var condition = node.JumpIfTrue ? value : !value;

                if (condition)
                {
                    return(Goto(syntax, node.Label));
                }
                else
                {
                    return(new BoundNopStatement(syntax));
                }
            }

            return(base.RewriteConditionalGotoStatement(node));
        }
Пример #11
0
        protected override BoundStatement RewriteWhileStatement(BoundWhileStatement node)
        {
            // goto check:
            // continue:
            // <body>
            // check:
            // gotoTrue condition continue:
            // end:
            // -------------------------------------------------------
            // later try out
            //- begin
            //- gotoFalse <condition> end
            //- <body>
            //-  goto begin
            //- end

            var endLabel      = GenerateLabel();
            var checkLabel    = GenerateLabel();
            var continueLabel = GenerateLabel();

            var gotoCheck = new BoundGotoStatement(checkLabel);
            var gotoTrue  = new BoundConditionalGotoStatement(continueLabel, node.Condition);

            var continueLabelStatement = new BoundLabelStatement(continueLabel);
            var checkLabelStatement    = new BoundLabelStatement(checkLabel);
            var endLabelStatement      = new BoundLabelStatement(endLabel);

            var result = new BoundBlockStatement(
                ImmutableArray.Create <BoundStatement>(
                    gotoCheck,
                    continueLabelStatement,
                    node.Body,
                    checkLabelStatement,
                    gotoTrue,
                    endLabelStatement));

            return(RewriteStatement(result));
        }
Пример #12
0
        protected override BoundStatement RewriteWhileStatement(BoundWhileStatement node)
        {
            // while <condition>
            //      <body>
            //
            // ----->
            //
            // goto continue
            // body:
            // <body>
            // continue:
            // gotoTrue <condition> body
            // break:
            //

            var bodyLabel = GenerateLabel();

            var gotoContinue           = new BoundGotoStatement(node.ContinueLabel);
            var bodyLabelStatement     = new BoundLabelStatement(bodyLabel);
            var continueLabelStatement = new BoundLabelStatement(node.ContinueLabel);
            var gotoTrue            = new BoundConditionalGotoStatement(bodyLabel, node.Condition);
            var breakLabelStatement = new BoundLabelStatement(node.BreakLabel);

            var result = new BoundBlockStatement(
                ImmutableArray.Create <BoundStatement>(
                    gotoContinue,
                    bodyLabelStatement,
                    node.Body,
                    continueLabelStatement,
                    gotoTrue,
                    breakLabelStatement
                    )
                );

            return(RewriteStatement(result));
        }
Пример #13
0
        protected override BoundStatement RewriteWhileStatement(BoundWhileStatement node)
        {
            // while <condition>
            //      <bode>
            //
            // ----->
            //
            // goto check
            // continue:
            // <body>
            // check:
            // gotoTrue <condition> continue
            // end:
            //

            var continueLabel = GenerateLabel();
            var checkLabel    = GenerateLabel();
            var endLabel      = GenerateLabel();

            var gotoCheck = new BoundGotoStatement(checkLabel);
            var continueLabelStatement = new BoundLabelStatement(continueLabel);
            var checkLabelStatement    = new BoundLabelStatement(checkLabel);
            var gotoTrue          = new BoundConditionalGotoStatement(continueLabel, node.Condition);
            var endLabelStatement = new BoundLabelStatement(endLabel);

            var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(
                                                     gotoCheck,
                                                     continueLabelStatement,
                                                     node.Body,
                                                     checkLabelStatement,
                                                     gotoTrue,
                                                     endLabelStatement
                                                     ));

            return(RewriteStatement(result));
        }
Пример #14
0
        protected override BoundStatement RewriteIfStatement(BoundIfStatement node)
        {
            if (node.ElseStatement == null)
            {
                var endLabel          = GenerateLabel();
                var gotoFalse         = new BoundConditionalGotoStatement(endLabel, node.Condition, true);
                var endLabelStatement = new BoundLabelStatement(endLabel);
                var result            = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(gotoFalse, node.Statement, endLabelStatement));
                return(RewriteStatement(result));
            }
            else
            {
                var elseLabel          = GenerateLabel();
                var endLabel           = GenerateLabel();
                var gotoFalse          = new BoundConditionalGotoStatement(elseLabel, node.Condition, true);
                var gotoEnd            = new BoundGotoStatement(endLabel);
                var elseLabelStatement = new BoundLabelStatement(elseLabel);
                var endLabelStatement  = new BoundLabelStatement(endLabel);

                var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(
                                                         gotoFalse, node.Statement, gotoEnd, elseLabelStatement, node.ElseStatement, endLabelStatement));
                return(RewriteStatement(result));
            }
        }
Пример #15
0
 private void EmitConditionalGotoStatement(ILProcessor ilProcessor, BoundConditionalGotoStatement node)
 {
     throw new NotImplementedException();
 }
Пример #16
0
        protected override BoundStatement RewriteForStatement(BoundForStatement node)
        {
            /*
             *
             * for <decl>, <condition>, <increment> {
             *  <body>
             * }
             *
             *
             * ----->
             *
             * {
             *  <decl>
             *  while <condition>{
             *      <body>
             *      continue:
             *      <increment>
             *  }
             *  break:
             * }
             *
             *
             * ----->
             *
             *
             * <decl>
             * goto check
             * body:
             * <body>
             * continue:
             * <increment>
             * check:
             * goto body if <condtiton>
             * break:
             */


            var decl      = node.VariableDeclaration;
            var increment = new BoundExpressionStatement(node.Increment, node.IsValid, true);
            var body      = node.Body;
            var condition = node.Condition;

            var bodyLabel     = CreateLabel();
            var continueLabel = node.ContinueLabel;
            var checkLabel    = CreateLabel();
            var breakLabel    = node.BreakLabel;

            var bodyLabelStmt     = new BoundLabelStatement(bodyLabel, node.IsValid);
            var continueLabelStmt = new BoundLabelStatement(continueLabel, node.IsValid);
            var checkLabelStmt    = new BoundLabelStatement(checkLabel, node.IsValid);
            var breakLabelStmt    = new BoundLabelStatement(breakLabel, node.IsValid);


            var gotoCheck    = new BoundGotoStatement(checkLabel, node.IsValid);
            var gotoTrueBody = new BoundConditionalGotoStatement(bodyLabel, node.Condition, jumpIfFalse: false, node.IsValid);

            var res = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(
                                                  decl,
                                                  gotoCheck,
                                                  bodyLabelStmt,
                                                  body,
                                                  continueLabelStmt,
                                                  increment,
                                                  checkLabelStmt,
                                                  gotoTrueBody,
                                                  breakLabelStmt
                                                  ), node.IsValid);

            return(RewriteStatement(res));
        }
Пример #17
0
        private object EvaluateStatement(BoundBlockStatement body)
        {
            var labelToIndex = new Dictionary <BoundLabel, int>();

            for (int i = 0; i < body.Statements.Length; i++)
            {
                if (body.Statements[i] is BoundLabelStatement l)
                {
                    labelToIndex.Add(l.Label, i + 1);
                }
            }

            int index = 0;

            while (index < body.Statements.Length)
            {
                BoundStatement s = body.Statements[index];

                switch (s.Kind)
                {
                case BoundNodeKind.VariableDeclaration:
                    EvaluateVariableDeclaration((BoundVariableDeclaration)s);
                    index++;
                    break;

                case BoundNodeKind.ExpressionStatement:
                    EvaluateExpressionStatement((BoundExpressionStatement)s);
                    index++;
                    break;

                case BoundNodeKind.GotoStatement:
                    BoundGotoStatement gs = (BoundGotoStatement)s;
                    index = labelToIndex[gs.Label];
                    break;

                case BoundNodeKind.ConditionalGotoStatement:
                    BoundConditionalGotoStatement cgs = (BoundConditionalGotoStatement)s;
                    bool condition = (bool)EvaluateExpression(cgs.Condition);
                    if (condition == cgs.JumpIfTrue)
                    {
                        index = labelToIndex[cgs.Label];
                    }
                    else
                    {
                        index++;
                    }
                    break;

                case BoundNodeKind.LabelStatement:
                    index++;
                    break;

                case BoundNodeKind.ReturnStatement:
                    BoundReturnStatement rs = (BoundReturnStatement)s;
                    lastValue = rs.Expression == null ? null : EvaluateExpression(rs.Expression);
                    return(lastValue);

                default:
                    throw new Exception($"Unexpected node <{s.Kind}>");
                }
            }

            return(lastValue);
        }
Пример #18
0
        /// <inheritdoc/>
        protected override BoundStatement RewriteForEllipsisStatement(BoundForEllipsisStatement node)
        {
            // for <var> := <lower> ... <upper>
            //      <body>
            //
            // ---->
            //
            // {
            //     var <var> = <lower>
            //     const upperBound = <upper>
            //     var step = 1
            //     if <var> greaterthan upperBound {
            //          step = -1
            //     }
            //     goto start
            //     body:
            //     <body>
            //     continue:
            //     <var> = <var> + step
            //     start:
            //     gotoTrue ((step > 0 && lower < upper) || (step < 0 && lower > upper)) body
            //     break:
            // }
            var variableDeclaration   = new BoundVariableDeclaration(node.Variable, node.LowerBound);
            var upperBoundSymbol      = new LocalVariableSymbol("upperBound", isReadOnly: true, type: TypeSymbol.Int);
            var upperBoundDeclaration = new BoundVariableDeclaration(upperBoundSymbol, node.UpperBound);
            var stepBoundSymbol       = new LocalVariableSymbol("step", isReadOnly: false, type: TypeSymbol.Int);
            var stepBoundDeclaration  = new BoundVariableDeclaration(
                variable: stepBoundSymbol,
                initializer: new BoundLiteralExpression(1));
            var variableExpression   = new BoundVariableExpression(node.Variable);
            var upperBoundExpression = new BoundVariableExpression(upperBoundSymbol);
            var stepBoundExpression  = new BoundVariableExpression(stepBoundSymbol);
            var ifLowerIsGreaterThanUpperExpression = new BoundBinaryExpression(
                left: variableExpression,
                op: BoundBinaryOperator.Bind(SyntaxKind.GreaterToken, TypeSymbol.Int, TypeSymbol.Int),
                right: upperBoundExpression);
            var stepBoundAssingment = new BoundExpressionStatement(
                expression: new BoundAssignmentExpression(
                    variable: stepBoundSymbol,
                    expression: new BoundLiteralExpression(-1)));
            var ifLowerIsGreaterThanUpperIfStatement = new BoundIfStatement(
                condition: ifLowerIsGreaterThanUpperExpression,
                thenStatement: stepBoundAssingment,
                elseStatement: null);
            var startLabel             = GenerateLabel();
            var gotoStart              = new BoundGotoStatement(startLabel);
            var bodyLabel              = GenerateLabel();
            var bodyLabelStatement     = new BoundLabelStatement(bodyLabel);
            var continueLabelStatement = new BoundLabelStatement(node.ContinueLabel);
            var increment              = new BoundExpressionStatement(
                expression: new BoundAssignmentExpression(
                    variable: node.Variable,
                    expression: new BoundBinaryExpression(
                        left: variableExpression,
                        op: BoundBinaryOperator.Bind(SyntaxKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int),
                        right: stepBoundExpression)));
            var startLabelStatement           = new BoundLabelStatement(startLabel);
            var zeroLiteralExpression         = new BoundLiteralExpression(0);
            var stepGreaterThanZeroExpression = new BoundBinaryExpression(
                left: stepBoundExpression,
                op: BoundBinaryOperator.Bind(SyntaxKind.GreaterToken, TypeSymbol.Int, TypeSymbol.Int),
                right: zeroLiteralExpression);
            var lowerLessThanUpperExpression = new BoundBinaryExpression(
                left: variableExpression,
                op: BoundBinaryOperator.Bind(SyntaxKind.LessToken, TypeSymbol.Int, TypeSymbol.Int),
                right: upperBoundExpression);
            var positiveStepAndLowerLessThanUpper = new BoundBinaryExpression(
                left: stepGreaterThanZeroExpression,
                op: BoundBinaryOperator.Bind(SyntaxKind.AmpersandAmpersandToken, TypeSymbol.Bool, TypeSymbol.Bool),
                right: lowerLessThanUpperExpression);
            var stepLessThanZeroExpression = new BoundBinaryExpression(
                left: stepBoundExpression,
                op: BoundBinaryOperator.Bind(SyntaxKind.LessToken, TypeSymbol.Int, TypeSymbol.Int),
                right: zeroLiteralExpression);
            var lowerGreaterThanUpperExpression = new BoundBinaryExpression(
                left: variableExpression,
                op: BoundBinaryOperator.Bind(SyntaxKind.GreaterToken, TypeSymbol.Int, TypeSymbol.Int),
                right: upperBoundExpression);
            var negativeStepAndLowerGreaterThanUpper = new BoundBinaryExpression(
                left: stepLessThanZeroExpression,
                op: BoundBinaryOperator.Bind(SyntaxKind.AmpersandAmpersandToken, TypeSymbol.Bool, TypeSymbol.Bool),
                right: lowerGreaterThanUpperExpression);
            var condition = new BoundBinaryExpression(
                positiveStepAndLowerLessThanUpper,
                BoundBinaryOperator.Bind(SyntaxKind.PipePipeToken, TypeSymbol.Bool, TypeSymbol.Bool),
                negativeStepAndLowerGreaterThanUpper);
            var gotoTrue            = new BoundConditionalGotoStatement(bodyLabel, condition, jumpIfTrue: true);
            var breakLabelStatement = new BoundLabelStatement(node.BreakLabel);

            var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(
                                                     variableDeclaration,
                                                     upperBoundDeclaration,
                                                     stepBoundDeclaration,
                                                     ifLowerIsGreaterThanUpperIfStatement,
                                                     gotoStart,
                                                     bodyLabelStatement,
                                                     node.Body,
                                                     continueLabelStatement,
                                                     increment,
                                                     startLabelStatement,
                                                     gotoTrue,
                                                     breakLabelStatement));

            return(RewriteStatement(result));
        }
Пример #19
0
        private static void WriteBoundConditionalGotoStatement(this IndentedTextWriter writer, BoundConditionalGotoStatement node)
        {
            writer.WriteMagentaKeyword("goto");
            writer.WriteSpace();
            writer.ColorWrite(node.Label.Identifier);
            writer.WriteSpace();

            if (node.JumpIfFalse)
            {
                writer.WriteMagentaKeyword("unless");
            }
            else
            {
                writer.WriteMagentaKeyword("if");
            }

            writer.WriteSpace();
            writer.WriteBoundNode(node.Condition);
        }
Пример #20
0
 public virtual void VisitConditionalGotoStatement(BoundConditionalGotoStatement node) =>
 this.DefaultVisit(node);