BitwiseOr() public abstract method

Pops two values from the stack, ORs them together, then pushes the result to the stack.
public abstract BitwiseOr ( ) : void
return void
        /// <summary>
        /// Generates IL for the script.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        protected override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Method signature: object FunctionDelegate(Compiler.Scope scope, object thisObject, Library.FunctionInstance functionObject, object[] arguments)

            // Initialize the scope (note: the initial scope for a function is always declarative).
            this.InitialScope.GenerateScopeCreation(generator, optimizationInfo);

            // Verify the scope is correct.
            VerifyScope(generator);

            // In ES3 the "this" value must be an object.  See 10.4.3 in the spec.
            if (this.StrictMode == false && this.MethodOptimizationHints.HasThis == true)
            {
                // if (thisObject == null || thisObject == Null.Value || thisObject == Undefined.Value)
                EmitHelpers.LoadThis(generator);
                generator.LoadNull();
                generator.CompareEqual();
                EmitHelpers.LoadThis(generator);
                EmitHelpers.EmitNull(generator);
                generator.CompareEqual();
                generator.BitwiseOr();
                EmitHelpers.LoadThis(generator);
                EmitHelpers.EmitUndefined(generator);
                generator.CompareEqual();
                generator.BitwiseOr();

                // {
                var startOfFalse = generator.CreateLabel();
                generator.BranchIfFalse(startOfFalse);

                // thisObject = engine.Global;
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Global);

                // } else {
                var endOfIf = generator.CreateLabel();
                generator.Branch(endOfIf);
                generator.DefineLabelPosition(startOfFalse);

                // thisObject = TypeConverter.ToObject(thisObject);
                EmitHelpers.LoadThis(generator);
                EmitConversion.ToObject(generator, PrimitiveType.Any, optimizationInfo);

                // }
                generator.DefineLabelPosition(endOfIf);
                EmitHelpers.StoreThis(generator);
            }

            // Transfer the function name into the scope.
            if (string.IsNullOrEmpty(this.Name) == false &&
                this.IncludeNameInScope == true &&
                this.ArgumentNames.Contains(this.Name) == false &&
                optimizationInfo.MethodOptimizationHints.HasVariable(this.Name))
            {
                EmitHelpers.LoadFunction(generator);
                var functionName = new NameExpression(this.InitialScope, this.Name);
                functionName.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false);
            }

            // Transfer the arguments object into the scope.
            if (this.MethodOptimizationHints.HasArguments == true && this.ArgumentNames.Contains("arguments") == false)
            {
                // prototype
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Object);
                generator.Call(ReflectionHelpers.FunctionInstance_InstancePrototype);
                // callee
                EmitHelpers.LoadFunction(generator);
                generator.CastClass(typeof(Library.UserDefinedFunction));
                // scope
                EmitHelpers.LoadScope(generator);
                generator.CastClass(typeof(DeclarativeScope));
                // argumentValues
                EmitHelpers.LoadArgumentsArray(generator);
                generator.NewObject(ReflectionHelpers.Arguments_Constructor);
                var arguments = new NameExpression(this.InitialScope, "arguments");
                arguments.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false);
            }

            // Transfer the argument values into the scope.
            // Note: the arguments array can be smaller than expected.
            if (this.ArgumentNames.Count > 0)
            {
                var endOfArguments = generator.CreateLabel();
                for (int i = 0; i < this.ArgumentNames.Count; i++)
                {
                    // Check if a duplicate argument name exists.
                    bool duplicate = false;
                    for (int j = i + 1; j < this.ArgumentNames.Count; j++)
                    {
                        if (this.ArgumentNames[i] == this.ArgumentNames[j])
                        {
                            duplicate = true;
                            break;
                        }
                    }
                    if (duplicate == true)
                    {
                        continue;
                    }

                    // Check if an array element exists.
                    EmitHelpers.LoadArgumentsArray(generator);
                    generator.LoadArrayLength();
                    generator.LoadInt32(i);
                    generator.BranchIfLessThanOrEqual(endOfArguments);

                    // Store the array element in the scope.
                    EmitHelpers.LoadArgumentsArray(generator);
                    generator.LoadInt32(i);
                    generator.LoadArrayElement(typeof(object));
                    var argument = new NameExpression(this.InitialScope, this.ArgumentNames[i]);
                    argument.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false);
                }
                generator.DefineLabelPosition(endOfArguments);
            }

            // Initialize any declarations.
            this.InitialScope.GenerateDeclarations(generator, optimizationInfo);

            //EmitHelpers.LoadScope(generator);
            //EmitConversion.ToObject(generator, PrimitiveType.Any);
            //generator.Pop();

            // Generate code for the body of the function.
            this.AbstractSyntaxTree.GenerateCode(generator, optimizationInfo);

            // Define the return target - this is where the return statement jumps to.
            // ReturnTarget can be null if there were no return statements.
            if (optimizationInfo.ReturnTarget != null)
            {
                generator.DefineLabelPosition(optimizationInfo.ReturnTarget);
            }

            // Load the return value.  If the variable is null, there were no return statements.
            if (optimizationInfo.ReturnVariable != null)
            {
                // Return the value stored in the variable.  Will be null if execution hits the end
                // of the function without encountering any return statements.
                generator.LoadVariable(optimizationInfo.ReturnVariable);
            }
            else
            {
                // There were no return statements - return null.
                generator.LoadNull();
            }
        }
Example #2
0
        /// <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 a return value is not expected, generate only the side-effects.

            /*if (optimizationInfo.SuppressReturnValue == true)
             * {
             *  this.GenerateSideEffects(generator, optimizationInfo);
             *  return;
             * }*/

            // Special case the addition operator.
            if (this.OperatorType == OperatorType.Add)
            {
                GenerateAdd(generator, optimizationInfo);
                return;
            }

            // Special case the instanceof operator.
            if (this.OperatorType == OperatorType.InstanceOf)
            {
                GenerateInstanceOf(generator, optimizationInfo);
                return;
            }

            // Special case the in operator.
            if (this.OperatorType == OperatorType.In)
            {
                GenerateIn(generator, optimizationInfo);
                return;
            }

            // Special case the relational operators.
            if (this.OperatorType == OperatorType.LessThan ||
                this.OperatorType == OperatorType.LessThanOrEqual ||
                this.OperatorType == OperatorType.GreaterThan ||
                this.OperatorType == OperatorType.GreaterThanOrEqual)
            {
                GenerateRelational(generator, optimizationInfo);
                return;
            }

            // Special case the logical operators.
            if (this.OperatorType == OperatorType.LogicalAnd ||
                this.OperatorType == OperatorType.LogicalOr)
            {
                GenerateLogical(generator, optimizationInfo);
                return;
            }

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

            // Convert the left argument.
            switch (this.OperatorType)
            {
            // Arithmetic operations.
            case OperatorType.Subtract:
            case OperatorType.Multiply:
            case OperatorType.Divide:
            case OperatorType.Modulo:
            case OperatorType.Exponentiation:
                EmitConversion.ToNumber(generator, this.Left.ResultType);
                break;

            // Bitwise operations.
            case OperatorType.BitwiseAnd:
            case OperatorType.BitwiseOr:
            case OperatorType.BitwiseXor:
            case OperatorType.LeftShift:
            case OperatorType.SignedRightShift:
            case OperatorType.UnsignedRightShift:
                EmitConversion.ToInt32(generator, this.Left.ResultType);
                break;

            // Equality operations.
            case OperatorType.Equal:
            case OperatorType.StrictlyEqual:
            case OperatorType.NotEqual:
            case OperatorType.StrictlyNotEqual:
                EmitConversion.ToAny(generator, this.Left.ResultType);
                break;
            }

            // Load the right hand side onto the stack.
            this.Right.GenerateCode(generator, optimizationInfo);

            // Convert the right argument.
            switch (this.OperatorType)
            {
            // Arithmetic operations.
            case OperatorType.Subtract:
            case OperatorType.Multiply:
            case OperatorType.Divide:
            case OperatorType.Modulo:
            case OperatorType.Exponentiation:
                EmitConversion.ToNumber(generator, this.Right.ResultType);
                break;

            // Bitwise operations.
            case OperatorType.BitwiseAnd:
            case OperatorType.BitwiseOr:
            case OperatorType.BitwiseXor:
                EmitConversion.ToInt32(generator, this.Right.ResultType);
                break;

            case OperatorType.LeftShift:
            case OperatorType.SignedRightShift:
            case OperatorType.UnsignedRightShift:
                EmitConversion.ToUInt32(generator, this.Right.ResultType);
                generator.LoadInt32(0x1F);
                generator.BitwiseAnd();
                break;

            // Equality operations.
            case OperatorType.Equal:
            case OperatorType.StrictlyEqual:
            case OperatorType.NotEqual:
            case OperatorType.StrictlyNotEqual:
                EmitConversion.ToAny(generator, this.Right.ResultType);
                break;
            }

            // Apply the operator.
            switch (this.OperatorType)
            {
            // Arithmetic operations.
            case OperatorType.Subtract:
                generator.Subtract();
                break;

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

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

            case OperatorType.Modulo:
                generator.Remainder();
                break;

            case OperatorType.Exponentiation:
                generator.CallStatic(ReflectionHelpers.Math_Pow);
                break;

            // Bitwise operations.
            case OperatorType.BitwiseAnd:
                generator.BitwiseAnd();
                break;

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

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

            // Shift operations.
            case OperatorType.LeftShift:
                generator.ShiftLeft();
                break;

            case OperatorType.SignedRightShift:
                generator.ShiftRight();
                break;

            case OperatorType.UnsignedRightShift:
                generator.ShiftRightUnsigned();
                EmitConversion.ToNumber(generator, PrimitiveType.UInt32);
                break;

            // Equality operations.
            case OperatorType.Equal:
                generator.Call(ReflectionHelpers.TypeComparer_Equals);
                break;

            case OperatorType.StrictlyEqual:
                generator.Call(ReflectionHelpers.TypeComparer_StrictEquals);
                break;

            case OperatorType.NotEqual:
                generator.Call(ReflectionHelpers.TypeComparer_Equals);
                generator.LoadBoolean(false);
                generator.CompareEqual();
                break;

            case OperatorType.StrictlyNotEqual:
                generator.Call(ReflectionHelpers.TypeComparer_StrictEquals);
                generator.LoadBoolean(false);
                generator.CompareEqual();
                break;

            default:
                throw new NotImplementedException(string.Format("Unsupported operator {0}", this.OperatorType));
            }
        }
        /// <summary>
        /// Generates IL for the script.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        protected override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Method signature: object FunctionDelegate(Compiler.Scope scope, object thisObject, Library.FunctionInstance functionObject, object[] arguments)

            // Initialize the scope (note: the initial scope for a function is always declarative).
            this.InitialScope.GenerateScopeCreation(generator, optimizationInfo);

            // Verify the scope is correct.
            VerifyScope(generator);

            // In ES3 the "this" value must be an object.  See 10.4.3 in the spec.
            if (this.StrictMode == false && this.MethodOptimizationHints.HasThis == true)
            {
                // if (thisObject == null || thisObject == Null.Value || thisObject == Undefined.Value)
                EmitHelpers.LoadThis(generator);
                generator.LoadNull();
                generator.CompareEqual();
                EmitHelpers.LoadThis(generator);
                EmitHelpers.EmitNull(generator);
                generator.CompareEqual();
                generator.BitwiseOr();
                EmitHelpers.LoadThis(generator);
                EmitHelpers.EmitUndefined(generator);
                generator.CompareEqual();
                generator.BitwiseOr();

                // {
                var startOfFalse = generator.CreateLabel();
                generator.BranchIfFalse(startOfFalse);

                // thisObject = engine.Global;
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Global);

                // } else {
                var endOfIf = generator.CreateLabel();
                generator.Branch(endOfIf);
                generator.DefineLabelPosition(startOfFalse);

                // thisObject = TypeConverter.ToObject(thisObject);
                EmitHelpers.LoadThis(generator);
                EmitConversion.ToObject(generator, PrimitiveType.Any);

                // }
                generator.DefineLabelPosition(endOfIf);
                EmitHelpers.StoreThis(generator);
            }

            // Transfer the function name into the scope.
            if (string.IsNullOrEmpty(this.Name) == false &&
                this.ArgumentNames.Contains(this.Name) == false &&
                optimizationInfo.MethodOptimizationHints.HasVariable(this.Name))
            {
                EmitHelpers.LoadFunction(generator);
                var functionName = new NameExpression(this.InitialScope, this.Name);
                functionName.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false);
            }

            // Transfer the arguments object into the scope.
            if (this.MethodOptimizationHints.HasArguments == true && this.ArgumentNames.Contains("arguments") == false)
            {
                // prototype
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Object);
                generator.Call(ReflectionHelpers.FunctionInstance_InstancePrototype);
                // callee
                EmitHelpers.LoadFunction(generator);
                generator.CastClass(typeof(Library.UserDefinedFunction));
                // scope
                EmitHelpers.LoadScope(generator);
                generator.CastClass(typeof(DeclarativeScope));
                // argumentValues
                EmitHelpers.LoadArgumentsArray(generator);
                generator.NewObject(ReflectionHelpers.Arguments_Constructor);
                var arguments = new NameExpression(this.InitialScope, "arguments");
                arguments.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false);
            }

            // Transfer the argument values into the scope.
            // Note: the arguments array can be smaller than expected.
            if (this.ArgumentNames.Count > 0)
            {
                var endOfArguments = generator.CreateLabel();
                for (int i = 0; i < this.ArgumentNames.Count; i++)
                {
                    // Check if a duplicate argument name exists.
                    bool duplicate = false;
                    for (int j = i + 1; j < this.ArgumentNames.Count; j++)
                        if (this.ArgumentNames[i] == this.ArgumentNames[j])
                        {
                            duplicate = true;
                            break;
                        }
                    if (duplicate == true)
                        continue;

                    // Check if an array element exists.
                    EmitHelpers.LoadArgumentsArray(generator);
                    generator.LoadArrayLength();
                    generator.LoadInt32(i);
                    generator.BranchIfLessThanOrEqual(endOfArguments);

                    // Store the array element in the scope.
                    EmitHelpers.LoadArgumentsArray(generator);
                    generator.LoadInt32(i);
                    generator.LoadArrayElement(typeof(object));
                    var argument = new NameExpression(this.InitialScope, this.ArgumentNames[i]);
                    argument.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false);
                }
                generator.DefineLabelPosition(endOfArguments);
            }

            // Initialize any declarations.
            this.InitialScope.GenerateDeclarations(generator, optimizationInfo);

            //EmitHelpers.LoadScope(generator);
            //EmitConversion.ToObject(generator, PrimitiveType.Any);
            //generator.Pop();

            // Generate code for the body of the function.
            this.AbstractSyntaxTree.GenerateCode(generator, optimizationInfo);

            // Define the return target - this is where the return statement jumps to.
            // ReturnTarget can be null if there were no return statements.
            if (optimizationInfo.ReturnTarget != null)
                generator.DefineLabelPosition(optimizationInfo.ReturnTarget);

            // Load the return value.  If the variable is null, there were no return statements.
            if (optimizationInfo.ReturnVariable != null)
                // Return the value stored in the variable.  Will be null if execution hits the end
                // of the function without encountering any return statements.
                generator.LoadVariable(optimizationInfo.ReturnVariable);
            else
                // There were no return statements - return null.
                generator.LoadNull();
        }
        /// <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 a return value is not expected, generate only the side-effects.
            /*if (optimizationInfo.SuppressReturnValue == true)
            {
                this.GenerateSideEffects(generator, optimizationInfo);
                return;
            }*/

            // Special case the addition operator.
            if (this.OperatorType == OperatorType.Add)
            {
                GenerateAdd(generator, optimizationInfo);
                return;
            }

            // Special case the instanceof operator.
            if (this.OperatorType == OperatorType.InstanceOf)
            {
                GenerateInstanceOf(generator, optimizationInfo);
                return;
            }

            // Special case the in operator.
            if (this.OperatorType == OperatorType.In)
            {
                GenerateIn(generator, optimizationInfo);
                return;
            }

            // Special case the relational operators.
            if (this.OperatorType == OperatorType.LessThan ||
                this.OperatorType == OperatorType.LessThanOrEqual ||
                this.OperatorType == OperatorType.GreaterThan ||
                this.OperatorType == OperatorType.GreaterThanOrEqual)
            {
                GenerateRelational(generator, optimizationInfo);
                return;
            }

            // Special case the logical operators.
            if (this.OperatorType == OperatorType.LogicalAnd ||
                this.OperatorType == OperatorType.LogicalOr)
            {
                GenerateLogical(generator, optimizationInfo);
                return;
            }

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

            // Convert the left argument.
            switch (this.OperatorType)
            {
                // Arithmetic operations.
                case OperatorType.Subtract:
                case OperatorType.Multiply:
                case OperatorType.Divide:
                case OperatorType.Modulo:
                    EmitConversion.ToNumber(generator, this.Left.ResultType);
                    break;

                // Bitwise operations.
                case OperatorType.BitwiseAnd:
                case OperatorType.BitwiseOr:
                case OperatorType.BitwiseXor:
                case OperatorType.LeftShift:
                case OperatorType.SignedRightShift:
                case OperatorType.UnsignedRightShift:
                    EmitConversion.ToInt32(generator, this.Left.ResultType);
                    break;

                // Equality operations.
                case OperatorType.Equal:
                case OperatorType.StrictlyEqual:
                case OperatorType.NotEqual:
                case OperatorType.StrictlyNotEqual:
                    EmitConversion.ToAny(generator, this.Left.ResultType);
                    break;
            }

            // Load the right hand side onto the stack.
            this.Right.GenerateCode(generator, optimizationInfo);

            // Convert the right argument.
            switch (this.OperatorType)
            {
                // Arithmetic operations.
                case OperatorType.Subtract:
                case OperatorType.Multiply:
                case OperatorType.Divide:
                case OperatorType.Modulo:
                    EmitConversion.ToNumber(generator, this.Right.ResultType);
                    break;

                // Bitwise operations.
                case OperatorType.BitwiseAnd:
                case OperatorType.BitwiseOr:
                case OperatorType.BitwiseXor:
                    EmitConversion.ToInt32(generator, this.Right.ResultType);
                    break;
                case OperatorType.LeftShift:
                case OperatorType.SignedRightShift:
                case OperatorType.UnsignedRightShift:
                    EmitConversion.ToUInt32(generator, this.Right.ResultType);
                    generator.LoadInt32(0x1F);
                    generator.BitwiseAnd();
                    break;

                // Equality operations.
                case OperatorType.Equal:
                case OperatorType.StrictlyEqual:
                case OperatorType.NotEqual:
                case OperatorType.StrictlyNotEqual:
                    EmitConversion.ToAny(generator, this.Right.ResultType);
                    break;
            }

            // Apply the operator.
            switch (this.OperatorType)
            {
                // Arithmetic operations.
                case OperatorType.Subtract:
                    generator.Subtract();
                    break;
                case OperatorType.Multiply:
                    generator.Multiply();
                    break;
                case OperatorType.Divide:
                    generator.Divide();
                    break;
                case OperatorType.Modulo:
                    generator.Remainder();
                    break;

                // Bitwise operations.
                case OperatorType.BitwiseAnd:
                    generator.BitwiseAnd();
                    break;
                case OperatorType.BitwiseOr:
                    generator.BitwiseOr();
                    break;
                case OperatorType.BitwiseXor:
                    generator.BitwiseXor();
                    break;

                // Shift operations.
                case OperatorType.LeftShift:
                    generator.ShiftLeft();
                    break;
                case OperatorType.SignedRightShift:
                    generator.ShiftRight();
                    break;
                case OperatorType.UnsignedRightShift:
                    generator.ShiftRightUnsigned();
                    EmitConversion.ToNumber(generator, PrimitiveType.UInt32);
                    break;

                // Equality operations.
                case OperatorType.Equal:
                    generator.Call(ReflectionHelpers.TypeComparer_Equals);
                    break;
                case OperatorType.StrictlyEqual:
                    generator.Call(ReflectionHelpers.TypeComparer_StrictEquals);
                    break;
                case OperatorType.NotEqual:
                    generator.Call(ReflectionHelpers.TypeComparer_Equals);
                    generator.LoadBoolean(false);
                    generator.CompareEqual();
                    break;
                case OperatorType.StrictlyNotEqual:
                    generator.Call(ReflectionHelpers.TypeComparer_StrictEquals);
                    generator.LoadBoolean(false);
                    generator.CompareEqual();
                    break;

                default:
                    throw new NotImplementedException(string.Format("Unsupported operator {0}", this.OperatorType));
            }
        }