protected override object EvaluateExpression(BoundExpression node)
        {
            if (node != null)
            {
                BoundLiteralExpression boundLiteralExpression;
                if ((boundLiteralExpression = (node as BoundLiteralExpression)) == null)
                {
                    BoundVariableExpression boundVariableExpression;
                    if ((boundVariableExpression = (node as BoundVariableExpression)) == null)
                    {
                        BoundAssignmentExpression boundAssignmentExpression;
                        if ((boundAssignmentExpression = (node as BoundAssignmentExpression)) == null)
                        {
                            BoundUnaryExpression boundUnaryExpression;
                            if ((boundUnaryExpression = (node as BoundUnaryExpression)) == null)
                            {
                                BoundBinaryExpression boundBinaryExpression;
                                if ((boundBinaryExpression = (node as BoundBinaryExpression)) != null)
                                {
                                    BoundBinaryExpression j = boundBinaryExpression;
                                    return(EvaluateBinaryExpression(j));
                                }
                                return(null);
                            }
                            return(EvaluateUnaryExpression(boundUnaryExpression));
                        }
                        return(EvaluateAssignmentExpression(boundAssignmentExpression));
                    }
                    return(EvaluateVariableExpression(boundVariableExpression));
                }
                return(EvaluateLiteralExpression(boundLiteralExpression));
            }

            return(null);
        }
Пример #2
0
        protected override BoundStatement RewriteForStatement(BoundForStatement node)
        {
            /*
             *  {
             *      let upperBound = <UpperBound>
             *      <variable> = <lowerBound>
             *      while <variable> < <UpperBound>
             *      {
             *          <statement>
             *          <variable> = <variable> + 1
             *      }
             *  }
             */

            var upperBoundSymbol      = new VariableSymbol("upperBound", true, node.UpperBound.Type, true);
            var upperBoundDeclaration = new BoundVariableDeclaration(upperBoundSymbol, node.UpperBound);
            var upperBoundExpression  = new BoundVariableExpression(upperBoundSymbol);
            var variableDeclaration   = new BoundVariableDeclaration(node.Variable, node.LowerBound); // LowerBound shouldn't be rewriten?
            var variableExpression    = new BoundVariableExpression(node.Variable);
            var conditionOperator     = BoundBinaryOperator.Bind(SyntaxKind.LessToken, TypeSymbol.Int, TypeSymbol.Int);
            var condition             = new BoundBinaryExpression(variableExpression, conditionOperator, upperBoundExpression); // UpperBound shouldn't be rewriten?

            var incrementOperator   = BoundBinaryOperator.Bind(SyntaxKind.PlusToken, node.Variable.Type, TypeSymbol.Int);
            var increment           = new BoundBinaryExpression(variableExpression, incrementOperator, new BoundLiteralExpression(1));
            var incrementAssignment = new BoundAssignmentExpression(node.Variable, increment);
            var incrementStatement  = new BoundExpressionStatement(incrementAssignment);

            var whileBlockStatement = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(node.Statement, incrementStatement));
            var whileStatement      = new BoundWhileStatement(condition, whileBlockStatement);

            var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(upperBoundDeclaration, variableDeclaration, whileStatement));

            return(RewriteStatement(result));
        }
Пример #3
0
        private object EvaluateBinaryExpression(BoundBinaryExpression expression)
        {
            object left  = EvaluateExpression(expression.LeftExpression);
            object right = EvaluateExpression(expression.RightExpression);
            var    op    = expression.Op;

            switch (op.OperatorType)
            {
            case BinaryOperatorType.Addition:
                return(OperatorEvaluator.EvaluateAddition(left, right, op));

            case BinaryOperatorType.Subtraction:
                return(OperatorEvaluator.EvaluateSubtraction(left, right, op));

            case BinaryOperatorType.Multiplication:
                return(OperatorEvaluator.EvaluateMultiplication(left, right, op));

            case BinaryOperatorType.Division:
                return(OperatorEvaluator.EvaluateDivision(left, right, op));

            case BinaryOperatorType.Power:
                return(OperatorEvaluator.EvaluatePower(left, right, op));

            case BinaryOperatorType.Modulus:
                return((int)left % (int)right);

            case BinaryOperatorType.Equality:
                return(OperatorEvaluator.EvaluateEquality(left, right, op));

            case BinaryOperatorType.NegatveEquality:
                return(!OperatorEvaluator.EvaluateEquality(left, right, op));

            case BinaryOperatorType.LogicalAnd:
                return((bool)left && (bool)right);

            case BinaryOperatorType.LogicalOr:
                return((bool)left || (bool)right);

            case BinaryOperatorType.LogicalXOr:
                return((bool)left ^ (bool)right);

            case BinaryOperatorType.GreaterThan:
                return(OperatorEvaluator.EvaluateGreaterThan(left, right, op));

            case BinaryOperatorType.LesserThan:
                return(OperatorEvaluator.EvaluateLesserThan(left, right, op));

            case BinaryOperatorType.StrictGreaterThan:
                return(OperatorEvaluator.EvaluateStrictGreaterThan(left, right, op));

            case BinaryOperatorType.StrinLesserThan:
                return(OperatorEvaluator.EvaluateStrictLesserThan(left, right, op));

            case BinaryOperatorType.Concatonate:
                return(OperatorEvaluator.EvaluateConcatonation(left, right));

            default:
                throw new Exception("Invalid operator");
            }
        }
Пример #4
0
 private void OutputBinaryExpression(BoundBinaryExpression node, string prefix)
 {
     builder.AddFragment(new OutputFragment(prefix, DefaultColour));
     Output(node.LeftExpression, string.Empty);
     builder.AddFragment(new OutputFragment($" {node.Op.TokenText} ", DefaultColour));
     Output(node.RightExpression, string.Empty);
 }
Пример #5
0
        private void EmitLogicalOrExpression(BoundBinaryExpression expression)
        {
            Debug.Assert(expression.Kind == TokenKind.Or, "Invalid expression kind.");

            string trySecondLabel = this.GenerateJumpLabel();
            string trueLabel      = this.GenerateJumpLabel();
            string falseLabel     = this.GenerateJumpLabel();
            string endLabel       = this.GenerateJumpLabel();

            TextRange expressionRange = expression.Syntax.Range;

            this.EmitExpression(expression.Left);
            this.instructions.Add(new TransientConditionalGoToInstruction(trueLabel, trySecondLabel, expressionRange));

            this.instructions.Add(new TransientLabelInstruction(trySecondLabel, expressionRange));
            this.EmitExpression(expression.Right);
            this.instructions.Add(new TransientConditionalGoToInstruction(null, falseLabel, expressionRange));

            TextRange endOfOperatorRange = this.instructions.Last().Range;

            this.instructions.Add(new TransientLabelInstruction(trueLabel, endOfOperatorRange));
            this.instructions.Add(new PushValueInstruction(new BooleanValue(true), endOfOperatorRange));
            this.instructions.Add(new TransientUnconditionalGoToInstruction(endLabel, endOfOperatorRange));

            this.instructions.Add(new TransientLabelInstruction(falseLabel, endOfOperatorRange));
            this.instructions.Add(new PushValueInstruction(new BooleanValue(false), endOfOperatorRange));

            this.instructions.Add(new TransientLabelInstruction(endLabel, endOfOperatorRange));
        }
Пример #6
0
        protected override BoundStatement RewriteForStatement(BoundForStatement node)
        {
            //For Statements are now all While Statements
            var variableDeclaration   = new BoundVariableDeclaration(node.Variable, node.LowerBound);
            var variableExpression    = new BoundVariableExpression(node.Variable);
            var upperBoundSymbol      = new VariableSymbol("upperBound", true, typeof(int));
            var upperBoundDeclaration = new BoundVariableDeclaration(upperBoundSymbol, node.UpperBound);
            var condition             = new BoundBinaryExpression(
                variableExpression,
                BoundBinaryOperator.Bind(SyntaxKind.LessOrEqualsToken, typeof(int), typeof(int)),
                new BoundVariableExpression(upperBoundSymbol)
                );
            var increment = new BoundExpressionStatement(
                new BoundAssignmentExpression(
                    node.Variable,
                    new BoundBinaryExpression(
                        variableExpression,
                        BoundBinaryOperator.Bind(SyntaxKind.PlusToken, typeof(int), typeof(int)),
                        new BoundLiteralExpression(1)
                        )
                    )
                );
            var whileBody      = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(node.Body, increment));
            var whileStatement = new BoundWhileStatement(condition, whileBody);
            var result         = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(
                                                             variableDeclaration,
                                                             upperBoundDeclaration,
                                                             whileStatement
                                                             ));

            return(RewriteStatement(result));
        }
Пример #7
0
        private object EvaluateBinaryExpression(BoundBinaryExpression b)
        {
            var left  = EvaluateExpression(b.Left);
            var right = EvaluateExpression(b.Right);

            switch (b.Op.Kind)
            {
            case BoundBinaryOperatorKind.Addition:
                return((int)left + (int)right);

            case BoundBinaryOperatorKind.Subtraction:
                return((int)left - (int)right);

            case BoundBinaryOperatorKind.Multiplication:
                return((int)left * (int)right);

            case BoundBinaryOperatorKind.Division:
                return((int)left / (int)right);

            case BoundBinaryOperatorKind.LogicalAnd:
                return((bool)left && (bool)right);

            case BoundBinaryOperatorKind.LogicalOr:
                return((bool)left || (bool)right);

            case BoundBinaryOperatorKind.Equals:
                return(Equals(left, right));

            case BoundBinaryOperatorKind.NotEquals:
                return(!Equals(left, right));

            default:
                throw new Exception($"Unexpected binary operator {b.Op}");
            }
        }
Пример #8
0
        protected override BoundExpression RewriteBinaryExpression(BoundBinaryExpression expression)
        {
            var op = expression.Op;

            BoundExpression newLeft  = RewriteExpression(expression.LeftExpression);
            BoundExpression newRight = RewriteExpression(expression.RightExpression);

            if (newLeft.ValueType != newRight.ValueType)
            {
                if (TypeConversionSymbol.TryFind(newLeft.ValueType, newRight.ValueType, out var leftConversion))
                {
                    newLeft = new BoundInternalTypeConversion(leftConversion, newLeft);
                }
                else if (TypeConversionSymbol.TryFind(newRight.ValueType, newLeft.ValueType, out var rightConversion))
                {
                    newRight = new BoundInternalTypeConversion(rightConversion, newRight);
                }
            }

            if (newLeft == expression.LeftExpression && newRight == expression.RightExpression)
            {
                return(expression);
            }

            return(new BoundBinaryExpression(newLeft, op, newRight));
        }
Пример #9
0
        protected override BoundExpression RewriteBinaryExpression(BoundBinaryExpression node)
        {
            if (!(node.Constant is null))
            {
                return(node);
            }

            if (node.Op == BoundBinaryOperator.LogicalAnd)
            {
                return(RewriteLogicalAnd(node));
            }

            if (node.Op == BoundBinaryOperator.LogicalOr)
            {
                return(RewriteLogicalOr(node));
            }

            var left  = RewriteExpression(node.Left);
            var right = RewriteExpression(node.Right);

            var leftType   = left.ResultType;
            var rightType  = right.ResultType;
            var oneLiteral = (BoundLiteralExpression?)null;

            if (node.Op == BoundBinaryOperator.Root)
            {
                oneLiteral = new BoundLiteralExpression(1.0d, TypeSymbol.Float, true);
            }

            switch (node.Op, leftType.Name, rightType.Name)
            {
Пример #10
0
        private object Evaluate(BoundBinaryExpression binaryExpression)
        {
            var left  = EvaluateExpression(binaryExpression.Left);
            var right = EvaluateExpression(binaryExpression.Right);

            switch (binaryExpression.Op.Kind)
            {
            case BoundBinaryOperatorKind.Addition:
                return((int)left + (int)right);

            case BoundBinaryOperatorKind.Subtraction:
                return((int)left - (int)right);

            case BoundBinaryOperatorKind.Multiplication:
                return((int)left * (int)right);

            case BoundBinaryOperatorKind.Division:
                return((int)left / (int)right);

            case BoundBinaryOperatorKind.LessThan:
                return((int)left < (int)right);

            case BoundBinaryOperatorKind.LessThanOrEquals:
                return((int)left <= (int)right);

            case BoundBinaryOperatorKind.GreaterThan:
                return((int)left > (int)right);

            case BoundBinaryOperatorKind.GreaterThanOrEquals:
                return((int)left >= (int)right);

            case BoundBinaryOperatorKind.LogicalAnd:
                return((bool)left && (bool)right);

            case BoundBinaryOperatorKind.LogicalOr:
                return((bool)left || (bool)right);

            case BoundBinaryOperatorKind.Equals:
                return(Equals(left, right));

            case BoundBinaryOperatorKind.NotEquals:
                return(!Equals(left, right));

            case BoundBinaryOperatorKind.BitwiseAnd:
                return(BitwiseAnd(left, right));

            case BoundBinaryOperatorKind.BitwiseOr:
                return(BitwiseOr(left, right));

            case BoundBinaryOperatorKind.BitwiseXor:
                return(BitwiseXor(left, right));

            default:
                throw new ArgumentOutOfRangeException(nameof(binaryExpression.Op.Kind), binaryExpression.Op.Kind, null);
            }
        }
Пример #11
0
        protected override BoundStatement RewriteForStatement(BoundForStatement node)
        {
            /*
             *  for <var> = <lower> to <upper>
             *      <body>
             *
             *  ----->
             *  {
             *      var <var> = <lower>
             *      let upperBound = <upper>
             *      while (<var> <= <upperBound>)
             *      {
             *          <body>
             *          <var> = <var> + 1
             *      }
             *  }
             */
            // var <var> = <lower>
            var variableDeclaration = new BoundVariableDeclaration(node.Variable, node.LowerBound);

            // let upperBound = <upper>
            var upperBoundSymbol      = new VariableSymbol("upperBound", true, TypeSymbol.Int);
            var upperBoundDeclaration = new BoundVariableDeclaration(upperBoundSymbol, node.UpperBound);

            // <var>
            var variableExpression = new BoundVariableExpression(node.Variable);

            //<var> <= <upperBound>
            var condition = new BoundBinaryExpression(
                variableExpression,
                BoundBinaryOperator.Bind(SyntaxKind.LessOrEqualsToken, TypeSymbol.Int, TypeSymbol.Int),
                new BoundVariableExpression(upperBoundSymbol)
                );

            // <var> = <var> + 1
            var increment = new BoundExpressionStatement(
                new BoundAssignmentExpression(
                    node.Variable,
                    new BoundBinaryExpression(
                        variableExpression,
                        BoundBinaryOperator.Bind(SyntaxKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int),
                        new BoundLiteralExpression(1)
                        )
                    )
                );

            var whileBlock     = new BoundBlockStatement(ImmutableArray.Create(node.Body, increment));
            var whileStatement = new BoundWhileStatement(condition, whileBlock);

            var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(
                                                     variableDeclaration,
                                                     upperBoundDeclaration,
                                                     whileStatement));

            return(RewriteStatement(result));
        }
Пример #12
0
        protected override BoundStatement RewriteForStatement(BoundForStatement node)
        {
            // for <var> = <lower> to <upper>
            //     <body>
            //
            // ---->
            // {
            //      var <var> = <lower>
            //      let upperBound = <upper>
            //      while (<var> <= upperBound)
            //      {
            //          <body>
            //          continue:
            //          <var> = <var> + 1
            //      }
            // }

            var variableDeclaration   = new BoundVariableDeclaration(node.Variable, node.LowerBound);
            var variableExpression    = new BoundVariableExpression(node.Variable);
            var upperBoundSymbol      = new LocalVariableSymbol("upperBound", true, TypeSymbol.Int);
            var upperBoundDeclaration = new BoundVariableDeclaration(upperBoundSymbol, node.UpperBound);
            var condition             = new BoundBinaryExpression(
                variableExpression,
                BoundBinaryOperator.Bind(SyntaxKind.LessOrEqualsToken, TypeSymbol.Int, TypeSymbol.Int),
                new BoundVariableExpression(upperBoundSymbol)
                );
            var continueLabelStatement = new BoundLabelStatement(node.ContinueLabel);
            var increment = new BoundExpressionStatement(
                new BoundAssignmentExpression(
                    node.Variable,
                    new BoundBinaryExpression(
                        variableExpression,
                        BoundBinaryOperator.Bind(SyntaxKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int),
                        new BoundLiteralExpression(1)
                        )
                    )
                );
            var whileBody = new BoundBlockStatement(
                ImmutableArray.Create <BoundStatement>(
                    node.Body,
                    continueLabelStatement,
                    increment
                    )
                );
            var whileStatement = new BoundWhileStatement(condition, whileBody, node.BreakLabel, GenerateLabel());
            var result         = new BoundBlockStatement(
                ImmutableArray.Create <BoundStatement>(
                    variableDeclaration,
                    upperBoundDeclaration,
                    whileStatement
                    )
                );

            return(RewriteStatement(result));
        }
Пример #13
0
        protected virtual BoundExpression RewriteBinaryExpression(BoundBinaryExpression expression)
        {
            var rewritenLeftExpresson  = RewriteExpression(expression.LeftExpression);
            var rewritenRightExpresson = RewriteExpression(expression.RightExpression);

            if (rewritenLeftExpresson == expression.LeftExpression && rewritenRightExpresson == expression.RightExpression)
            {
                return(expression);
            }

            return(new BoundBinaryExpression(rewritenLeftExpresson, expression.Op, rewritenRightExpresson));
        }
Пример #14
0
        private object EvaluateBinaryExpression(BoundBinaryExpression b)
        {
            var left  = EvaluateExpression(b.Left);
            var right = EvaluateExpression(b.Right);

            switch (b.Operator.Kind)
            {
            case BoundBinaryOperatorKind.Addition:
                return((int)left + (int)right);

            case BoundBinaryOperatorKind.Subtraction:
                return((int)left - (int)right);

            case BoundBinaryOperatorKind.Multiplication:
                return((int)left * (int)right);

            case BoundBinaryOperatorKind.Division:
                return((int)left / (int)right);

            case BoundBinaryOperatorKind.LogicalAnd:
                return((bool)left && (bool)right);

            case BoundBinaryOperatorKind.LogicalOr:
                return((bool)left || (bool)right);

            case BoundBinaryOperatorKind.Equal:
                return(Equals(left, right));

            case BoundBinaryOperatorKind.BangEquals:
                return(!Equals(left, right));

            case BoundBinaryOperatorKind.MathmaticalAnd:
                return((int)left & (int)right);

            case BoundBinaryOperatorKind.MathmaticalOr:
                return((int)left | (int)right);

            case BoundBinaryOperatorKind.LeftShift:
                return((int)left << (int)right);

            case BoundBinaryOperatorKind.RIghtShift:
                return((int)left >> (int)right);

            case BoundBinaryOperatorKind.BiggerCompare:
                return((int)left > (int)right);

            case BoundBinaryOperatorKind.LessCompare:
                return((int)left < (int)right);

            default:
                throw new Exception($"Error: Unexpected Binary Operator <{b.Operator}>");
            }
        }
Пример #15
0
    protected override BoundExpression RewriteBinaryExpression(BoundBinaryExpression node)
    {
        var left      = IsSimpleNode(node.Left) ? node.Left : CreateTemporary(node.Left);
        var right     = IsSimpleNode(node.Right) ? node.Right : CreateTemporary(node.Right);
        var @operator = RewriteBinaryOperator(node.Operator);

        if (node.Left == left && node.Right == right && node.Operator == @operator)
        {
            return(node);
        }

        return(new BoundBinaryExpression(node.Syntax, left, @operator, right));
    }
Пример #16
0
            public override void VisitAssignmentStatement(AssignmentStatement node)
            {
                var left  = Bind(node.Left) !;
                var right = Bind(node.Right) !;

                if (node.Op != null)
                {
                    // transform 'left op= right' to 'left = left op right'
                    // TODO: this may cause 'left' to be evaluated twice (e.g. function call that returns a reference)
                    right = new BoundBinaryExpression(left, right, node.Op.Value);
                }

                stmts !.Add(new BoundAssignmentStatement(left, right));
            }
Пример #17
0
        protected override BoundStatement RewriteForToStatement(BoundForToStatement node)
        {
            // for <var> = <lower> to <upper> <body>
            // --- to --->
            // {
            // var <var> = <lower>
            // let upperBound = <upper>
            // while <var> <= upperBound
            //     <body>
            //     continue:
            //     <var> = <var> + 1
            // }

            var variableDeclaration
                = new BoundVariableDeclarationStatement(node.Variable, node.LowerBound);

            var upperBoundSymbol = new LocalVariableSymbol("upperBound", true, TypeSymbol.Int);
            var upperBoundDeclaration
                = new BoundVariableDeclarationStatement(upperBoundSymbol, node.UpperBound);
            var upperBoundExpression = new BoundVariableExpression(upperBoundSymbol);

            var condition = new BoundBinaryExpression(
                new BoundVariableExpression(node.Variable),
                BoundBinaryOperator.Bind(Lexing.TokenKind.LessOrEquals, TypeSymbol.Int, TypeSymbol.Int),
                upperBoundExpression);

            var increment = new BoundExpressionStatement(
                new BoundAssignmentExpression(
                    node.Variable,
                    new BoundBinaryExpression(
                        new BoundVariableExpression(node.Variable),
                        BoundBinaryOperator.Bind(Lexing.TokenKind.Plus, TypeSymbol.Int, TypeSymbol.Int),
                        new BoundLiteralExpression(1))));

            var whileBlock =
                new BoundBlockStatement(
                    node.Body,
                    increment);

            var whileStatement
                = new BoundWhileStatement(condition, whileBlock, node.BreakLabel, node.ContinueLabel);

            var result = new BoundBlockStatement(
                variableDeclaration,
                upperBoundDeclaration,
                whileStatement);

            return(RewriteStatement(result));
        }
Пример #18
0
        public void TestBinaryExpression()
        {
            const int Left = -5, Right = 3;

            var expr = new BoundBinaryExpression(
                new BoundIntLiteralExpression(Left),
                new BoundIntLiteralExpression(Right),
                BinaryOperator.Add
                );

            var result = Evaluator.Evaluate(expr);

            Assert.Single(result);
            Assert.Equal(Left + Right, result[0].AsInt32);
        }
Пример #19
0
    public override void VisitBinaryExpression(BoundBinaryExpression node)
    {
        var op =
            SyntaxFacts.GetText(node.Operator.SyntaxKind)
            ?? throw new Exception("Invalid operator");
        var precedence =
            node.Operator.SyntaxKind.GetBinaryOperatorPrecedence()
            ?? throw new Exception("Invalid operator");

        WriteNestedExpression(node.Left, precedence);
        _writer.Write(" ");
        _writer.WritePunctuation(op);
        _writer.Write(" ");
        WriteNestedExpression(node.Right, precedence);
    }
Пример #20
0
 protected override object EvaluateExpression(BoundExpression node)
 {
     try
     {
         BoundLiteralExpression boundLiteralExpression = (BoundLiteralExpression)node;
         return(EvaluateLiteralExpression(boundLiteralExpression));
     }
     catch
     {
         try
         {
             BoundVariableExpression boundVariableExpression = (BoundVariableExpression)node;
             return(EvaluateVariableExpression(boundVariableExpression));
         }
         catch
         {
             try
             {
                 BoundAssignmentExpression boundAssignmentExpression = (BoundAssignmentExpression)node;
                 return(EvaluateAssignmentExpression(boundAssignmentExpression));
             }
             catch
             {
                 try
                 {
                     BoundUnaryExpression boundUnaryExpression = (BoundUnaryExpression)node;
                     return(EvaluateUnaryExpression(boundUnaryExpression));
                 }
                 catch
                 {
                     try
                     {
                         BoundBinaryExpression boundBinaryExpression = (BoundBinaryExpression)node;
                         return(EvaluateBinaryExpression(boundBinaryExpression));
                     }
                     catch
                     {
                         return(null);
                     }
                 }
             }
         }
     }
 }
Пример #21
0
        protected override BoundStatement RewriteForStatement(BoundForStatement node)
        {
            // for <var> = <lower> to <upper>
            //      <body>
            //
            // ---->
            //
            // {
            //      var <var> = <lower>
            //      while (<var> <= <upper>)
            //      {
            //          <body>
            //          <var> = <var> + 1
            //      }
            // }

            var variableDeclaration   = new BoundVeriableDeclaration(node.Variable, node.LowerBound);
            var variableExpression    = new BoundVariableExpression(node.Variable);
            var upperBoundSybmle      = new VariableSymble("upperBound", true, typeof(int));
            var upperBoundDeclaration = new BoundVeriableDeclaration(upperBoundSybmle, node.UpperBound);
            var condition             = new BoundBinaryExpression(
                variableExpression,
                BoundBinaryOperator.Bind(SyntaxKind.LessOrEqualToken, typeof(int), typeof(int)),
                new BoundVariableExpression(upperBoundSybmle)
                );
            var increment = new BoundExpressionStatemnet(
                new BoundAssignmentExpression(
                    node.Variable,
                    new BoundBinaryExpression(
                        variableExpression,
                        BoundBinaryOperator.Bind(SyntaxKind.PlusToken, typeof(int), typeof(int)),
                        new BoundLiteralExpression(1)
                        )
                    )
                );
            var whileBody      = new BoundBlockStatemnet(ImmutableArray.Create <BoundStatement>(node.Body, increment));
            var whileStatement = new BoundWhileStatement(condition, whileBody);
            var result         = new BoundBlockStatemnet(ImmutableArray.Create <BoundStatement>(
                                                             variableDeclaration, upperBoundDeclaration, whileStatement));

            return(RewriteStatement(result));
        }
Пример #22
0
 private void EmitBinaryExpression(ILProcessor ilProcessor, BoundBinaryExpression node)
 {
     if (node.Op.Kind == BoundBinaryOperatorKind.Addition)
     {
         if (node.Left.Type == TypeSymbol.String &&
             node.Right.Type == TypeSymbol.String)
         {
             EmitExpression(ilProcessor, node.Left);
             EmitExpression(ilProcessor, node.Right);
             ilProcessor.Emit(OpCodes.Call, _stringConcatReference);
         }
         else
         {
             throw new NotImplementedException();
         }
     }
     else
     {
         throw new NotImplementedException();
     }
 }
Пример #23
0
        protected override BoundStatement RewriteForStatement(BoundForStatement node)
        {
            // for <var> = <lower> to <upper>
            //  <body>
            // is rewritten to
            //  {
            //    var <Var> = <lower>
            //  while ()
            //
            var variableDeclaration = new BoundVariableDeclaration(node.Variable, node.LowerBound);
            var variableExpression  = new BoundVariableExpression(node.Variable);

            var condition = new BoundBinaryExpression(
                variableExpression,
                BoundBinaryOperator.Bind(SyntaxKind.LessOrEqualsToken, typeof(int), typeof(int)),
                node.UpperBound);

            var increment = new BoundExpressionStatement(
                new BoundAssignmentExpression(
                    node.Variable,
                    new BoundBinaryExpression(
                        variableExpression,
                        BoundBinaryOperator.Bind(
                            SyntaxKind.PlusToken,
                            typeof(int),
                            typeof(int)),
                        new BoundLiteralExpression(1)
                        )
                    )
                );

            var whileBlock = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(node.Body, increment));

            var whileStatement = new BoundWhileStatement(condition, whileBlock);

            var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(variableDeclaration, whileStatement));

            return(RewriteStatement(result));
        }
Пример #24
0
        protected override BoundStatement RewriteForStatement(BoundForStatement node)
        {
            BoundVariableDeclaration variableDeclaration      = new BoundVariableDeclaration(node.Variable, node.LowerBound);
            BoundVariableExpression  variableExpression       = new BoundVariableExpression(node.Variable);
            VariableSymbol           upperVariableSymbol      = new LocalVariableSymbol("upperBound", true, TypeSymbol.Int);
            BoundVariableDeclaration upperVariableDeclaration = new BoundVariableDeclaration(upperVariableSymbol, node.UpperBound);

            BoundBinaryExpression condition = new BoundBinaryExpression(
                variableExpression,
                BoundBinaryOperator.Bind(SyntaxKind.LessOrEqualsToken, TypeSymbol.Int, TypeSymbol.Int),
                new BoundVariableExpression(upperVariableSymbol)
                );
            BoundLabelStatement      continueLabelStatement = new BoundLabelStatement(node.ContinueLabel);
            BoundExpressionStatement increment = new BoundExpressionStatement(
                new BoundAssignmentExpression(
                    node.Variable,
                    new BoundBinaryExpression(
                        variableExpression,
                        BoundBinaryOperator.Bind(SyntaxKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int),
                        new BoundLiteralExpression(1)
                        )
                    )
                );

            BoundBlockStatement whileBody = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(
                                                                        node.Body,
                                                                        continueLabelStatement,
                                                                        increment
                                                                        ));
            BoundWhileStatement whileStatement = new BoundWhileStatement(condition, whileBody, node.BreakLabel, GenerateLabel());

            BoundBlockStatement result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(
                                                                     variableDeclaration,
                                                                     upperVariableDeclaration,
                                                                     whileStatement
                                                                     ));

            return(RewriteStatement(result));
        }
Пример #25
0
            public override void VisitRepeatStatement(RepeatStatement node)
            {
                // reduce REPEAT statement to a WHILE statement

                /* REPEAT n i
                 *    block
                 * ENDREPEAT
                 *
                 * i = 0
                 * WHILE i < n
                 *    block
                 *    i = i + 1
                 * ENDWHILE
                 */

                var boundLimit   = Bind(node.Limit) !;
                var boundCounter = Bind(node.Counter) !;

                // i = 0
                var zeroCounter = new BoundAssignmentStatement(boundCounter, new BoundIntLiteralExpression(0));

                stmts !.Add(zeroCounter);

                // WHILE i < n
                var condition  = new BoundBinaryExpression(boundCounter, boundLimit, BinaryOperator.Less);
                var boundWhile = new BoundWhileStatement(condition);

                stmts !.Add(boundWhile);

                VisitScope(node.Block, boundWhile.Block);

                // i = i + 1
                var add    = new BoundBinaryExpression(boundCounter, new BoundIntLiteralExpression(1), BinaryOperator.Add);
                var assign = new BoundAssignmentStatement(boundCounter, add);

                boundWhile.Block.Add(assign);
            }
Пример #26
0
        private void EmitBinaryExpression(BoundBinaryExpression expression)
        {
            BaseInstruction binaryInstruction;

            switch (expression.Kind)
            {
            case TokenKind.Or: this.EmitLogicalOrExpression(expression); return;

            case TokenKind.And: this.EmitLogicalAndExpression(expression); return;

            case TokenKind.Equal: binaryInstruction = new EqualInstruction(expression.Syntax.Range); break;

            case TokenKind.NotEqual: binaryInstruction = new NotEqualInstruction(expression.Syntax.Range); break;

            case TokenKind.LessThan: binaryInstruction = new LessThanInstruction(expression.Syntax.Range); break;

            case TokenKind.LessThanOrEqual: binaryInstruction = new LessThanOrEqualInstruction(expression.Syntax.Range); break;

            case TokenKind.GreaterThan: binaryInstruction = new GreaterThanInstruction(expression.Syntax.Range); break;

            case TokenKind.GreaterThanOrEqual: binaryInstruction = new GreaterThanOrEqualInstruction(expression.Syntax.Range); break;

            case TokenKind.Plus: binaryInstruction = new AddInstruction(expression.Syntax.Range); break;

            case TokenKind.Minus: binaryInstruction = new SubtractInstruction(expression.Syntax.Range); break;

            case TokenKind.Multiply: binaryInstruction = new MultiplyInstruction(expression.Syntax.Range); break;

            case TokenKind.Divide: binaryInstruction = new DivideInstruction(expression.Syntax.Range); break;

            default: throw ExceptionUtilities.UnexpectedValue(expression.Kind);
            }

            this.EmitExpression(expression.Left);
            this.EmitExpression(expression.Right);
            this.instructions.Add(binaryInstruction);
        }
Пример #27
0
        private object EvaluateBinaryExpression(BoundBinaryExpression bt)
        {
            var left  = EvaluateExpression(bt.Left);
            var right = EvaluateExpression(bt.Right);

            switch (bt.Op.Kind)
            {
            case BoundBinaryOperatorKind.Addition:
                return((int)left + (int)right);

            case BoundBinaryOperatorKind.Subtraction:
                return((int)left - (int)right);

            case BoundBinaryOperatorKind.Multiplication:
                return((int)left * (int)right);

            case BoundBinaryOperatorKind.Division:
                return((int)left / (int)right);

            case BoundBinaryOperatorKind.BitwiseAnd:
                if (bt.Left.Type == typeof(int))
                {
                    return((int)left & (int)right);
                }
                else
                {
                    return((bool)left & (bool)right);
                }

            case BoundBinaryOperatorKind.BitwiseOr:
                if (bt.Left.Type == typeof(int))
                {
                    return((int)left | (int)right);
                }
                else
                {
                    return((bool)left | (bool)right);
                }

            case BoundBinaryOperatorKind.BitwiseXor:
                if (bt.Left.Type == typeof(int))
                {
                    return((int)left ^ (int)right);
                }
                else
                {
                    return((bool)left ^ (bool)right);
                }

            case BoundBinaryOperatorKind.LogicalAnd:
                return((bool)left && (bool)right);

            case BoundBinaryOperatorKind.LogicalOr:
                return((bool)left || (bool)right);

            case BoundBinaryOperatorKind.Equals:
                return(Equals(left, right));

            case BoundBinaryOperatorKind.NotEquals:
                return(!Equals(left, right));

            case BoundBinaryOperatorKind.Less:
                return((int)left < (int)right);

            case BoundBinaryOperatorKind.LessOrEquals:
                return((int)left <= (int)right);

            case BoundBinaryOperatorKind.Greater:
                return((int)left > (int)right);

            case BoundBinaryOperatorKind.GreaterOrEquals:
                return((int)left >= (int)right);

            default:
                throw new Exception($"Expected a binary operator {bt.Op.Kind}");
            }
        }
Пример #28
0
        private object EvaluateBinaryExpression(BoundBinaryExpression b)
        {
            var left  = EvaluateExpression(b.Left);
            var right = EvaluateExpression(b.Right);

            switch (b.Op.Kind)
            {
            case BoundBinaryOperatorKind.Addition:
                return((int)left + (int)right);

            case BoundBinaryOperatorKind.Subtraction:
                return((int)left - (int)right);

            case BoundBinaryOperatorKind.Multiplication:
                return((int)left * (int)right);

            case BoundBinaryOperatorKind.Division:
                return((int)left / (int)right);

            case BoundBinaryOperatorKind.BitwiseAnd:
                if (b.Type == TypeSymbol.Int)
                {
                    return((int)left & (int)right);
                }
                else
                {
                    return((bool)left & (bool)right);
                }

            case BoundBinaryOperatorKind.BitwiseOr:
                if (b.Type == TypeSymbol.Int)
                {
                    return((int)left | (int)right);
                }
                else
                {
                    return((bool)left | (bool)right);
                }

            case BoundBinaryOperatorKind.BitwiseXOr:
                if (b.Type == TypeSymbol.Int)
                {
                    return((int)left ^ (int)right);
                }
                else
                {
                    return((bool)left ^ (bool)right);
                }

            case BoundBinaryOperatorKind.LogicalAndAlso:
                return((bool)left && (bool)right);

            case BoundBinaryOperatorKind.LogicalOrElse:
                return((bool)left || (bool)right);

            case BoundBinaryOperatorKind.Equals:
                return(Equals(left, right));

            case BoundBinaryOperatorKind.NotEquals:
                return(!Equals(left, right));

            case BoundBinaryOperatorKind.LessThan:
                return((int)left < (int)right);

            case BoundBinaryOperatorKind.LessThanOrEqual:
                return((int)left <= (int)right);

            case BoundBinaryOperatorKind.GreaterThan:
                return((int)left > (int)right);

            case BoundBinaryOperatorKind.GreaterThanOrEqual:
                return((int)left >= (int)right);

            default:
                throw new Exception($"Unexpected binary operator {b.Op}");
            }
        }
Пример #29
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));
        }
Пример #30
0
 private static void WriteBoundBinaryExpression(this IndentedTextWriter writer, BoundBinaryExpression node)
 {
     writer.ColorWrite("(");
     writer.WriteBoundNode(node.Left);
     writer.WriteSpace();
     writer.ColorWrite(node.Op.GetText());
     writer.WriteSpace();
     writer.WriteBoundNode(node.Right);
     writer.ColorWrite(")");
 }