/// <summary>
        /// Generates CIL for the expression.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Special-case the delete operator.
            if (this.OperatorType == OperatorType.Delete)
            {
                GenerateDelete(generator, optimizationInfo);
                return;
            }

            // Special-case the typeof operator.
            if (this.OperatorType == OperatorType.Typeof)
            {
                GenerateTypeof(generator, optimizationInfo);
                return;
            }

            // Load the operand onto the stack.
            this.Operand.GenerateCode(generator, optimizationInfo);

            // If we're not using the return value, pop and quit.
            if (optimizationInfo.RootExpression == this)
            {
                // Pop it and quit.
                generator.Pop();
                return;
            }

            // Convert the operand to the correct type.
            switch (this.OperatorType)
            {
            case OperatorType.Plus:
            case OperatorType.Minus:
                EmitConversion.ToNumber(generator, this.Operand.GetResultType(optimizationInfo));
                break;

            case OperatorType.BitwiseNot:
                EmitConversion.ToInt32(generator, this.Operand.GetResultType(optimizationInfo));
                break;

            case OperatorType.LogicalNot:
                EmitConversion.ToBool(generator, this.Operand.GetResultType(optimizationInfo));
                break;
            }

            // Apply the operator.
            switch (this.OperatorType)
            {
            case OperatorType.Plus:
                break;

            case OperatorType.Minus:
                generator.Negate();
                break;

            case OperatorType.BitwiseNot:
                generator.BitwiseNot();
                break;

            case OperatorType.LogicalNot:
                generator.LoadBoolean(false);
                generator.CompareEqual();
                break;

            case OperatorType.Void:
                generator.Pop();
                EmitHelpers.EmitUndefined(generator);
                break;

            default:
                throw new NotImplementedException(string.Format("Unsupported operator {0}", this.OperatorType));
            }
        }
Beispiel #2
0
        /// <summary>
        /// Generates CIL for the statement.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Get the root:
            Expression prevRoot = optimizationInfo.RootExpression;

            // Is the condition constant?
            if (StaticResult != null)
            {
                // We have a compile-time constant (i.e. if(true) )

                // Convert it to a bool:
                bool result = TypeConverter.ToBoolean(StaticResult);

                if (result)
                {
                    // if(true)

                    // Generate code for the if clause which is now the root:
                    IfClause.SetRoot(optimizationInfo);

                    IfClause.GenerateCode(generator, optimizationInfo);
                }
                else
                {
                    // if(false)

                    if (ElseClause != null)
                    {
                        // It's now the root:
                        ElseClause.SetRoot(optimizationInfo);

                        // Code for the else clause:
                        ElseClause.GenerateCode(generator, optimizationInfo);
                    }
                }

                // Restore root:
                optimizationInfo.RootExpression = prevRoot;

                return;
            }

            // Generate code for the condition and coerce to a boolean.
            this.Condition.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToBool(generator, this.Condition.GetResultType(optimizationInfo));

            // We will need a label at the end of the if statement.
            var endOfEverything = generator.CreateLabel();

            if (this.ElseClause == null)
            {
                // Jump to the end if the condition is false.
                generator.BranchIfFalse(endOfEverything);

                // If clause is now the root:
                IfClause.SetRoot(optimizationInfo);

                // Generate code for the if clause.
                IfClause.GenerateCode(generator, optimizationInfo);
            }
            else
            {
                // Branch to the else clause if the condition is false.
                var startOfElseClause = generator.CreateLabel();
                generator.BranchIfFalse(startOfElseClause);

                // If clause is now the root:
                IfClause.SetRoot(optimizationInfo);

                // Generate code for the if clause.
                IfClause.GenerateCode(generator, optimizationInfo);

                // Branch to the end of the if statement.
                generator.Branch(endOfEverything);

                // Else clause is now the root:
                ElseClause.SetRoot(optimizationInfo);

                // Generate code for the else clause.
                generator.DefineLabelPosition(startOfElseClause);
                ElseClause.GenerateCode(generator, optimizationInfo);
            }

            // Define the label at the end of the if statement.
            generator.DefineLabelPosition(endOfEverything);

            // Restore root:
            optimizationInfo.RootExpression = prevRoot;
        }
        /// <summary>
        /// Generates CIL for the expression.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // If our host is a root then we are also a root.
            Expression prevRoot = optimizationInfo.RootExpression;

            Expression operand2 = this.GetOperand(1);
            Expression operand3 = this.GetOperand(2);

            if (StaticResult != null)
            {
                // Going one way or the other statically!

                // Convert it to a bool:
                bool result = TypeConverter.ToBoolean(StaticResult);

                if (result)
                {
                    // if(true)

                    if (prevRoot == this)
                    {
                        // Host is a root therefore we are one now:
                        optimizationInfo.RootExpression = operand2;
                    }

                    // Generate code for the if clause:
                    operand2.GenerateCode(generator, optimizationInfo);
                }
                else
                {
                    // if(false)

                    if (prevRoot == this)
                    {
                        // Host is a root therefore we are one now:
                        optimizationInfo.RootExpression = operand3;
                    }

                    // Code for the else clause:
                    operand3.GenerateCode(generator, optimizationInfo);
                }

                // Restore root:
                optimizationInfo.RootExpression = prevRoot;
                return;
            }

            // Emit the condition.
            var condition = this.GetOperand(0);

            condition.GenerateCode(generator, optimizationInfo);

            // Convert the condition to a boolean.
            EmitConversion.ToBool(generator, condition.GetResultType(optimizationInfo));

            // Branch if the condition is false.
            var startOfElse = generator.CreateLabel();

            generator.BranchIfFalse(startOfElse);

            // Calculate the result type.
            var outputType = this.GetResultType(optimizationInfo);

            if (prevRoot == this)
            {
                // Host is a root therefore we are one now:
                optimizationInfo.RootExpression = operand2;
            }

            // Emit the second operand and convert it to the result type.
            operand2.GenerateCode(generator, optimizationInfo);
            EmitConversion.Convert(generator, operand2.GetResultType(optimizationInfo), outputType, optimizationInfo);

            // Branch to the end.
            var end = generator.CreateLabel();

            generator.Branch(end);
            generator.DefineLabelPosition(startOfElse);

            if (prevRoot == this)
            {
                // Host is a root therefore we are one now:
                optimizationInfo.RootExpression = operand3;
            }

            // Emit the third operand and convert it to the result type.
            operand3.GenerateCode(generator, optimizationInfo);
            EmitConversion.Convert(generator, operand3.GetResultType(optimizationInfo), outputType, optimizationInfo);

            // Define the end label.
            generator.DefineLabelPosition(end);

            // Restore root:
            optimizationInfo.RootExpression = prevRoot;
        }
        /// <summary>
        /// Generates CIL for the logical operators.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        private void GenerateLogical(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // If either evaluates statically to 0 then we also know the correct return type.
            object leftEval = Left.Evaluate();

            if (leftEval != null)
            {
                // RHS only.

                bool leftTrue = TypeConverter.ToBoolean(leftEval);

                // a && b
                // If a is false, don't do anything with b.
                // If a is true, emit b.
                // a || b
                // If a is false, emit b. If it's true, emit a.

                if (OperatorType == OperatorType.LogicalAnd && !leftTrue)
                {
                    // Don't evaluate the RHS. Just emit a 'false' if one is needed.
                    if (optimizationInfo.RootExpression != this)
                    {
                        // Emit the false:
                        generator.LoadBoolean(false);
                    }
                }
                else if (OperatorType == OperatorType.LogicalOr && leftTrue)
                {
                    // Emit the left object only.
                    if (optimizationInfo.RootExpression != this)
                    {
                        // Load it:
                        EmitHelpers.EmitValue(generator, leftEval);
                    }
                }
                else if (optimizationInfo.RootExpression == this)
                {
                    // Emitting b (no return type required).

                    // Right will be the root instead.
                    optimizationInfo.RootExpression = Right;
                    Right.GenerateCode(generator, optimizationInfo);
                    optimizationInfo.RootExpression = this;
                }
                else
                {
                    // Emitting b (return type required).

                    // Output required.
                    Right.GenerateCode(generator, optimizationInfo);
                }

                return;
            }

            // Evaluate B, just in case we're doing RHS only:
            object rightEval = Right.Evaluate();

            // Get the statically-determined types of the left and right operands.
            Type leftType  = this.Left.GetResultType(optimizationInfo);
            Type rightType = rightEval == null?this.Right.GetResultType(optimizationInfo) : rightEval.GetType();

            // Load the left-hand side operand.
            this.Left.GenerateCode(generator, optimizationInfo);

            // Make sure the output type is consistant.
            if (leftType != rightType)
            {
                if (PrimitiveTypeUtilities.IsNumeric(leftType) == true && PrimitiveTypeUtilities.IsNumeric(rightType) == true)
                {
                    EmitConversion.ToNumber(generator, leftType);
                    leftType = typeof(double);
                }
                else
                {
                    EmitConversion.ToAny(generator, leftType);
                    leftType = typeof(object);
                }
            }

            // If this is an OR, we might be using the value currently on the stack if it's true.
            // So, duplicate:
            if (OperatorType == OperatorType.LogicalOr && optimizationInfo.RootExpression != this)
            {
                generator.Duplicate();
            }

            // Convert to a boolean:
            EmitConversion.ToBool(generator, leftType);

            // If this is an AND, we might be using the value currently on the stack if it's false.
            // So, duplicate:
            if (OperatorType == OperatorType.LogicalAnd && optimizationInfo.RootExpression != this)
            {
                generator.Duplicate();
            }

            // Stack contains:
            // OR: "left, (bool)left"
            // AND: "(bool)left, (bool)left"

            var endOfIf = generator.CreateLabel();

            if (this.OperatorType == OperatorType.LogicalAnd)
            {
                generator.BranchIfFalse(endOfIf);
            }
            else
            {
                generator.BranchIfTrue(endOfIf);
            }

            if (optimizationInfo.RootExpression == this)
            {
                // Right hand side will now be the root (output is not in use).
                optimizationInfo.RootExpression = Right;

                Right.GenerateCode(generator, optimizationInfo);

                // Restore:
                optimizationInfo.RootExpression = this;
            }
            else
            {
                // Stack contains "left" which we don't need if we fall through here. Pop it off:
                generator.Pop();

                // Output is in use.
                Right.GenerateCode(generator, optimizationInfo);

                // Make sure the output type is consistant.
                if (leftType != rightType)
                {
                    if (PrimitiveTypeUtilities.IsNumeric(leftType) == true && PrimitiveTypeUtilities.IsNumeric(rightType) == true)
                    {
                        EmitConversion.ToNumber(generator, rightType);
                    }
                    else
                    {
                        EmitConversion.ToAny(generator, rightType);
                    }
                }
            }

            // Define the label used above.
            generator.DefineLabelPosition(endOfIf);
        }
Beispiel #5
0
        /// <summary>
        /// Generates CIL for the statement.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Get the previous root - we'll be changing it:
            Expression prevRoot = optimizationInfo.RootExpression;

            List <string> labels = optimizationInfo.Labels;

            optimizationInfo.Labels = null;

            // Emit the initialization statement.
            if (InitStatement != null)
            {
                // Init isn't in use. Mark it as root:
                InitStatement.SetRoot(optimizationInfo);

                InitStatement.GenerateCode(generator, optimizationInfo);

                // Restore root:
                optimizationInfo.RootExpression = prevRoot;
            }

            var startOfLoop    = generator.DefineLabelPosition();
            var continueTarget = generator.CreateLabel();
            var endOfLoop      = generator.CreateLabel();

            bool conditionAtEnd = CheckConditionAtEnd;

            // AT END..
            // top:
            // <body statements>
            // continue:
            // <increment>
            // if(condition)
            // <goto top>
            // break:

            // top:
            // if(!condition)
            // <goto break>
            // <body statements>
            // continue:
            // <increment>
            // <goto top>
            // break:

            if (!conditionAtEnd)
            {
                if (ConditionStatement != null)
                {
                    Condition.GenerateCode(generator, optimizationInfo);
                    EmitConversion.ToBool(generator, Condition.GetResultType(optimizationInfo));
                    generator.BranchIfFalse(endOfLoop);
                }
            }

            // Emit the loop body.
            optimizationInfo.PushBreakOrContinueInfo(labels, endOfLoop, continueTarget, false);

            // Mark the body as root:
            Body.SetRoot(optimizationInfo);

            Body.GenerateCode(generator, optimizationInfo);
            optimizationInfo.PopBreakOrContinueInfo();

            generator.DefineLabelPosition(continueTarget);

            // Increment the loop variable.
            if (IncrementStatement != null)
            {
                // Increment isn't in use. Mark it as root:
                IncrementStatement.SetRoot(optimizationInfo);

                IncrementStatement.GenerateCode(generator, optimizationInfo);
            }

            // Restore root:
            optimizationInfo.RootExpression = prevRoot;

            if (conditionAtEnd)
            {
                if (ConditionStatement != null)
                {
                    // Emit now:
                    Condition.GenerateCode(generator, optimizationInfo);
                    EmitConversion.ToBool(generator, Condition.GetResultType(optimizationInfo));
                    generator.BranchIfTrue(startOfLoop);
                }
            }
            else
            {
                generator.Branch(startOfLoop);
            }

            generator.DefineLabelPosition(endOfLoop);
        }