NewArray() public abstract method

Pops the size of the array off the stack and pushes a new array of the given type onto the stack.
public abstract NewArray ( Type type ) : void
type System.Type The element type.
return void
        /// <summary>
        /// Generates an array containing the argument values.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        internal void GenerateArgumentsArray(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Emit the arguments.  The arguments operand can be non-existant, a single expression,
            // or a comma-delimited list.
            if (this.OperandCount < 2)
            {
                // No parameters passed.  Create an empty array.
                generator.LoadInt32(0);
                generator.NewArray(typeof(object));
            }
            else
            {
                // One or more arguments.
                IList <Expression> arguments;
                var argumentsOperand = this.GetRawOperand(1);
                if (argumentsOperand is ListExpression)
                {
                    // Multiple parameters were passed to the function.
                    arguments = ((ListExpression)argumentsOperand).Items;
                }
                else if (argumentsOperand is TemplateLiteralExpression)
                {
                    // Tagged template literal.
                    var templateLiteral = (TemplateLiteralExpression)argumentsOperand;
                    GenerateTemplateArgumentsArray(generator, optimizationInfo, templateLiteral);
                    return;
                }
                else
                {
                    // A single parameter was passed to the function.
                    arguments = new List <Expression>(1)
                    {
                        argumentsOperand
                    };
                }

                // Generate an array containing the value of each argument.
                generator.LoadInt32(arguments.Count);
                generator.NewArray(typeof(object));
                for (int i = 0; i < arguments.Count; i++)
                {
                    generator.Duplicate();
                    generator.LoadInt32(i);
                    arguments[i].GenerateCode(generator, optimizationInfo);
                    EmitConversion.ToAny(generator, arguments[i].ResultType);
                    generator.StoreArrayElement(typeof(object));
                }
            }
        }
        /// <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)
        {
            // This code is only used for untagged template literals.
            // Tagged template literals are handled by FunctionCallExpression.

            // Load the values array onto the stack.
            generator.LoadInt32(this.Strings.Count + this.Values.Count);
            generator.NewArray(typeof(string));
            for (int i = 0; i < this.Strings.Count; i++)
            {
                // Operands for StoreArrayElement() are: an array (string[]), index (int), value (string).

                // Store the string.
                generator.Duplicate();
                generator.LoadInt32(i * 2);
                generator.LoadString(this.Strings[i]);
                generator.StoreArrayElement(typeof(string));

                if (i == this.Strings.Count - 1)
                {
                    break;
                }

                // Store the value.
                generator.Duplicate();
                generator.LoadInt32(i * 2 + 1);
                this.Values[i].GenerateCode(generator, optimizationInfo);
                EmitConversion.ToString(generator, this.Values[i].ResultType);
                generator.StoreArrayElement(typeof(string));
            }

            // Call String.Concat(string[])
            generator.CallStatic(ReflectionHelpers.String_Concat);
        }
Example #3
0
        /// <summary>
        /// Generates an array containing the argument values for a tagged template literal.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        /// <param name="templateLiteral"> The template literal expression containing the parameter
        /// values. </param>
        internal void GenerateTemplateArgumentsArray(ILGenerator generator, OptimizationInfo optimizationInfo, TemplateLiteralExpression templateLiteral)
        {
            // Generate an array containing the value of each argument.
            generator.LoadInt32(templateLiteral.Values.Count + 1);
            generator.NewArray(typeof(object));

            // Load the first parameter.
            generator.Duplicate();
            generator.LoadInt32(0);

            // The first parameter to the tag function is an array of strings.
            var stringsExpression = new List <Expression>(templateLiteral.Strings.Count);

            foreach (var templateString in templateLiteral.Strings)
            {
                stringsExpression.Add(new LiteralExpression(templateString));
            }
            new LiteralExpression(stringsExpression).GenerateCode(generator, optimizationInfo);
            generator.Duplicate();

            // Now we need the name of the property.
            generator.LoadString("raw");

            // Now generate an array of raw strings.
            var rawStringsExpression = new List <Expression>(templateLiteral.RawStrings.Count);

            foreach (var rawString in templateLiteral.RawStrings)
            {
                rawStringsExpression.Add(new LiteralExpression(rawString));
            }
            new LiteralExpression(rawStringsExpression).GenerateCode(generator, optimizationInfo);

            // Freeze array by calling ObjectInstance Freeze(ObjectInstance).
            generator.CallStatic(ReflectionHelpers.ObjectConstructor_Freeze);

            // Now store the raw strings as a property of the base strings array.
            generator.LoadBoolean(optimizationInfo.StrictMode);
            generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_Object);

            // Freeze array by calling ObjectInstance Freeze(ObjectInstance).
            generator.CallStatic(ReflectionHelpers.ObjectConstructor_Freeze);

            // Store in the array.
            generator.StoreArrayElement(typeof(object));

            // Values are passed as subsequent parameters.
            for (int i = 0; i < templateLiteral.Values.Count; i++)
            {
                generator.Duplicate();
                generator.LoadInt32(i + 1);
                templateLiteral.Values[i].GenerateCode(generator, optimizationInfo);
                EmitConversion.ToAny(generator, templateLiteral.Values[i].ResultType);
                generator.StoreArrayElement(typeof(object));
            }
        }
Example #4
0
        /// <summary>
        /// Generates CIL for the in operator.
        /// </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 GenerateIn(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Emit the left-hand side expression and convert it to a string.
            this.Left.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToString(generator, this.Left.ResultType);

            // Store the left-hand side expression in a temporary variable.
            var temp = generator.CreateTemporaryVariable(typeof(string));

            generator.StoreVariable(temp);

            // Emit the right-hand side expression.
            this.Right.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToAny(generator, this.Right.ResultType);

            // Check the right-hand side is a javascript object - if not, throw an exception.
            generator.Duplicate();
            generator.IsInstance(typeof(ObjectInstance));
            var endOfTypeCheck = generator.CreateLabel();

            generator.BranchIfTrue(endOfTypeCheck);

            // Throw an nicely formatted exception.
            var rightValue = generator.CreateTemporaryVariable(typeof(object));

            generator.StoreVariable(rightValue);
            generator.LoadEnumValue(ErrorType.TypeError);
            generator.LoadString("The in operator expected an object, but found '{0}' instead");
            generator.LoadInt32(1);
            generator.NewArray(typeof(object));
            generator.Duplicate();
            generator.LoadInt32(0);
            generator.LoadVariable(rightValue);
            generator.Call(ReflectionHelpers.TypeUtilities_TypeOf);
            generator.StoreArrayElement(typeof(object));
            generator.Call(ReflectionHelpers.String_Format);
            generator.LoadInt32(optimizationInfo.SourceSpan.StartLine);
            generator.LoadStringOrNull(optimizationInfo.Source.Path);
            generator.LoadStringOrNull(optimizationInfo.FunctionName);
            generator.NewObject(ReflectionHelpers.JavaScriptException_Constructor_Error);
            generator.Throw();
            generator.DefineLabelPosition(endOfTypeCheck);
            generator.ReleaseTemporaryVariable(rightValue);
            generator.ReinterpretCast(typeof(ObjectInstance));

            // Load the left-hand side expression from the temporary variable.
            generator.LoadVariable(temp);

            // Call ObjectInstance.HasProperty(object)
            generator.Call(ReflectionHelpers.ObjectInstance_HasProperty);

            // Allow the temporary variable to be reused.
            generator.ReleaseTemporaryVariable(temp);
        }
Example #5
0
        /// <summary>
        /// Generates CIL for the instanceof operator.
        /// </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 GenerateInstanceOf(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Emit the left-hand side expression and convert it to an object.
            this.Left.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToAny(generator, this.Left.ResultType);

            // Store the left-hand side expression in a temporary variable.
            var temp = generator.CreateTemporaryVariable(typeof(object));

            generator.StoreVariable(temp);

            // Emit the right-hand side expression.
            this.Right.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToAny(generator, this.Right.ResultType);

            // Check the right-hand side is a function - if not, throw an exception.
            generator.IsInstance(typeof(Library.FunctionInstance));
            generator.Duplicate();
            var endOfTypeCheck = generator.CreateLabel();

            generator.BranchIfNotNull(endOfTypeCheck);

            // Throw an nicely formatted exception.
            var rightValue = generator.CreateTemporaryVariable(typeof(object));

            generator.StoreVariable(rightValue);
            EmitHelpers.LoadScriptEngine(generator);
            generator.LoadString("TypeError");
            generator.LoadString("The instanceof operator expected a function, but found '{0}' instead");
            generator.LoadInt32(1);
            generator.NewArray(typeof(object));
            generator.Duplicate();
            generator.LoadInt32(0);
            generator.LoadVariable(rightValue);
            generator.Call(ReflectionHelpers.TypeUtilities_TypeOf);
            generator.StoreArrayElement(typeof(object));
            generator.Call(ReflectionHelpers.String_Format);
            generator.NewObject(ReflectionHelpers.JavaScriptException_Constructor_Error);
            generator.Throw();
            generator.DefineLabelPosition(endOfTypeCheck);
            generator.ReleaseTemporaryVariable(rightValue);

            // Load the left-hand side expression from the temporary variable.
            generator.LoadVariable(temp);

            // Call FunctionInstance.HasInstance(object)
            generator.Call(ReflectionHelpers.FunctionInstance_HasInstance);

            // Allow the temporary variable to be reused.
            generator.ReleaseTemporaryVariable(temp);
        }
        /// <summary>
        /// Generates code that creates a new scope.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        internal override void GenerateScopeCreation(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Allocate storage for each variable if the declarative scope object has been optimized away.
            if (optimizationInfo.OptimizeDeclarativeScopes == false)
            {
                // Create a new declarative scope.

                // parentScope
                EmitHelpers.LoadScope(generator);

                // declaredVariableNames
                generator.LoadInt32(this.DeclaredVariableCount);
                generator.NewArray(typeof(string));
                int i = 0;
                foreach (string variableName in this.DeclaredVariableNames)
                {
                    generator.Duplicate();
                    generator.LoadInt32(i++);
                    generator.LoadString(variableName);
                    generator.StoreArrayElement(typeof(string));
                }

                // DeclarativeScope.CreateRuntimeScope(parentScope, declaredVariableNames)
                generator.Call(ReflectionHelpers.DeclarativeScope_CreateRuntimeScope);

                // Save the new scope.
                EmitHelpers.StoreScope(generator);
            }
            else
            {
                // The declarative scope can be optimized away entirely.
                foreach (var variable in this.DeclaredVariables)
                {
                    variable.Store = null;
                    variable.Type  = PrimitiveType.Any;
                }

                // Indicate the scope was not created.
                this.ExistsAtRuntime = false;
            }
        }
Example #7
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)
        {
            // Operands for ArrayConstructor.New() are: an ArrayConstructor instance (ArrayConstructor), an array (object[])
            // ArrayConstructor
            EmitHelpers.LoadScriptEngine(generator);
            generator.Call(ReflectionHelpers.ScriptEngine_Array);

            // object[]
            generator.LoadInt32(Items.Count);
            generator.NewArray(typeof(object));
            for (int i = 0; i < Items.Count; i++)
            {
                // Operands for StoreArrayElement() are: an array (object[]), index (int), value (object).
                // Array
                generator.Duplicate();

                // Index
                generator.LoadInt32(i);

                // Value
                var elementExpression = Items[i];
                if (elementExpression == null)
                {
                    generator.LoadNull();
                }
                else
                {
                    elementExpression.GenerateCode(generator, optimizationInfo);
                    EmitConversion.ToAny(generator, elementExpression.ResultType);
                }

                // Store the element value.
                generator.StoreArrayElement(typeof(object));
            }

            // ArrayConstructor.New(object[])
            generator.Call(ReflectionHelpers.Array_New);
        }
Example #8
0
        /// <summary>
        /// Gets an enumerable list of argument objects, equal in size to
        /// <paramref name="argumentCount"/> while generating code to prepare those arguments for
        /// a method call.
        /// </summary>
        /// <param name="argumentCount"> The number of arguments to return. </param>
        /// <param name="generator"> The IL generator used to create an array if the method has a
        /// ParamArray parameter. </param>
        /// <returns> An enumerable list of argument objects. </returns>
        public IEnumerable <BinderArgument> GenerateArguments(ILGenerator generator, int argumentCount)
        {
            if (generator == null)
            {
                throw new ArgumentNullException(nameof(generator));
            }

            int paramArrayIndex = 0;

            foreach (var argument in this.GetArguments(argumentCount))
            {
                if (argument.IsParamArrayArgument == true)
                {
                    if (paramArrayIndex == 0)
                    {
                        // This is the start of the ParamArray arguments.
                        // Create an array.
                        int paramArraySize = Math.Max(0, argumentCount - this.OptionalParameterCount - this.RequiredParameterCount);
                        generator.LoadInt32(paramArraySize);
                        generator.NewArray(argument.Type);
                    }

                    // Load the array and index.
                    generator.Duplicate();
                    generator.LoadInt32(paramArrayIndex++);
                }

                // Yield will have the side effect of generating a value.
                yield return(argument);

                if (argument.IsParamArrayArgument == true)
                {
                    // Store the value in the ParamArray array.
                    generator.StoreArrayElement(argument.Type);
                }
            }

            // Populate any missing optional arguments with the default value.
            if (this.RequiredParameterCount + this.OptionalParameterCount - argumentCount > 0)
            {
                var parameters = this.GetParameters();
                for (int i = 0; i < this.RequiredParameterCount + this.OptionalParameterCount - argumentCount; i++)
                {
                    var optionalParameter = parameters[argumentCount + i];
                    if ((optionalParameter.Attributes & ParameterAttributes.HasDefault) == ParameterAttributes.HasDefault)
                    {
                        // Emit the default value.
                        EmitHelpers.EmitValue(generator, new BinderArgument(optionalParameter, 0).DefaultValue);
                    }
                    else
                    {
                        // Emit default(T).
                        EmitHelpers.EmitDefaultValue(generator, optionalParameter.ParameterType);
                    }
                }
            }

            // Create an empty array if a ParamArray argument exists but no arguments were provided.
            if (this.HasParamArray == true && paramArrayIndex == 0)
            {
                // Create an array.
                generator.LoadInt32(0);
                generator.NewArray(this.ParamArrayElementType);
            }
        }
        /// <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)
        {
            // Literals cannot have side-effects so if a return value is not expected then generate
            // nothing.
            //if (optimizationInfo.SuppressReturnValue == true)
            //    return;

            if (this.Value is int)
            {
                generator.LoadInt32((int)this.Value);
            }
            else if (this.Value is double)
            {
                generator.LoadDouble((double)this.Value);
            }
            else if (this.Value is string)
            {
                generator.LoadString((string)this.Value);
            }
            else if (this.Value is bool)
            {
                generator.LoadBoolean((bool)this.Value);
            }
            else if (this.Value is RegularExpressionLiteral)
            {
                // RegExp
                var sharedRegExpVariable = optimizationInfo.GetRegExpVariable(generator, (RegularExpressionLiteral)this.Value);
                var label1 = generator.CreateLabel();
                var label2 = generator.CreateLabel();

                // if (sharedRegExp == null) {
                generator.LoadVariable(sharedRegExpVariable);
                generator.LoadNull();
                generator.BranchIfNotEqual(label1);

                // sharedRegExp = Global.RegExp.Construct(source, flags)
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_RegExp);
                generator.LoadString(((RegularExpressionLiteral)this.Value).Pattern);
                generator.LoadString(((RegularExpressionLiteral)this.Value).Flags);
                generator.Call(ReflectionHelpers.RegExp_Construct);
                generator.Duplicate();
                generator.StoreVariable(sharedRegExpVariable);

                // } else {
                generator.Branch(label2);
                generator.DefineLabelPosition(label1);

                // Global.RegExp.Construct(sharedRegExp, flags)
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_RegExp);
                generator.LoadVariable(sharedRegExpVariable);
                generator.LoadNull();
                generator.Call(ReflectionHelpers.RegExp_Construct);

                // }
                generator.DefineLabelPosition(label2);
            }
            else if (this.Value == Null.Value)
            {
                // Null.
                EmitHelpers.EmitNull(generator);
            }
            else if (this.Value == Undefined.Value)
            {
                // Undefined.
                EmitHelpers.EmitUndefined(generator);
            }
            else if (this.Value is List <Expression> )
            {
                // Construct an array literal.
                var arrayLiteral = (List <Expression>) this.Value;

                // Operands for ArrayConstructor.New() are: an ArrayConstructor instance (ArrayConstructor), an array (object[])
                // ArrayConstructor
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Array);

                // object[]
                generator.LoadInt32(arrayLiteral.Count);
                generator.NewArray(typeof(object));
                for (int i = 0; i < arrayLiteral.Count; i++)
                {
                    // Operands for StoreArrayElement() are: an array (object[]), index (int), value (object).
                    // Array
                    generator.Duplicate();

                    // Index
                    generator.LoadInt32(i);

                    // Value
                    var elementExpression = arrayLiteral[i];
                    if (elementExpression == null)
                    {
                        generator.LoadNull();
                    }
                    else
                    {
                        elementExpression.GenerateCode(generator, optimizationInfo);
                        EmitConversion.ToAny(generator, elementExpression.ResultType);
                    }

                    // Store the element value.
                    generator.StoreArrayElement(typeof(object));
                }

                // ArrayConstructor.New(object[])
                generator.Call(ReflectionHelpers.Array_New);
            }
            else if (this.Value is List <KeyValuePair <Expression, Expression> > )
            {
                // This is an object literal.
                var properties = (List <KeyValuePair <Expression, Expression> >) this.Value;

                // Create a new object.
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Object);
                generator.Call(ReflectionHelpers.Object_Construct);

                foreach (var keyValuePair in properties)
                {
                    Expression propertyName  = keyValuePair.Key;
                    Expression propertyValue = keyValuePair.Value;

                    generator.Duplicate();

                    // The key can be a property name or an expression that evaluates to a name.
                    propertyName.GenerateCode(generator, optimizationInfo);
                    EmitConversion.ToPropertyKey(generator, propertyName.ResultType);

                    var functionValue = propertyValue as FunctionExpression;
                    if (functionValue != null && functionValue.DeclarationType == FunctionDeclarationType.Getter)
                    {
                        // Add a getter to the object.
                        functionValue.GenerateCode(generator, optimizationInfo);
                        // Support the inferred function displayName property.
                        if (propertyName is LiteralExpression && ((LiteralExpression)propertyName).Value is string)
                        {
                            functionValue.GenerateDisplayName(generator, optimizationInfo, "get " + (string)((LiteralExpression)propertyName).Value, true);
                        }
                        generator.Call(ReflectionHelpers.ReflectionHelpers_SetObjectLiteralGetter);
                    }
                    else if (functionValue != null && functionValue.DeclarationType == FunctionDeclarationType.Setter)
                    {
                        // Add a setter to the object.
                        functionValue.GenerateCode(generator, optimizationInfo);
                        // Support the inferred function displayName property.
                        if (propertyName is LiteralExpression && ((LiteralExpression)propertyName).Value is string)
                        {
                            functionValue.GenerateDisplayName(generator, optimizationInfo, "set " + (string)((LiteralExpression)propertyName).Value, true);
                        }
                        generator.Call(ReflectionHelpers.ReflectionHelpers_SetObjectLiteralSetter);
                    }
                    else
                    {
                        // Add a new property to the object.
                        propertyValue.GenerateCode(generator, optimizationInfo);
                        // Support the inferred function displayName property.
                        if (propertyValue is FunctionExpression && propertyName is LiteralExpression && ((LiteralExpression)propertyName).Value is string)
                        {
                            ((FunctionExpression)propertyValue).GenerateDisplayName(generator, optimizationInfo, (string)((LiteralExpression)propertyName).Value, false);
                        }
                        EmitConversion.ToAny(generator, propertyValue.ResultType);
                        generator.Call(ReflectionHelpers.ReflectionHelpers_SetObjectLiteralValue);
                    }
                }
            }
            else
            {
                throw new NotImplementedException("Unknown literal type.");
            }
        }
        /// <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)
        {
            // Note: we use GetRawOperand() so that grouping operators are not ignored.
            var operand = this.GetRawOperand(0);

            // There is only one operand, and it can be either a reference or a function call.
            // We need to split the operand into a function and some arguments.
            // If the operand is a reference, it is equivalent to a function call with no arguments.
            if (operand is FunctionCallExpression)
            {
                // Emit the function instance first.
                var function = ((FunctionCallExpression)operand).Target;
                function.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToAny(generator, function.ResultType);
            }
            else
            {
                // Emit the function instance first.
                operand.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToAny(generator, operand.ResultType);
            }

            // Check the object really is a function - if not, throw an exception.
            generator.IsInstance(typeof(Library.FunctionInstance));
            generator.Duplicate();
            var endOfTypeCheck = generator.CreateLabel();
            generator.BranchIfNotNull(endOfTypeCheck);

            // Throw an nicely formatted exception.
            var targetValue = generator.CreateTemporaryVariable(typeof(object));
            generator.StoreVariable(targetValue);
            EmitHelpers.LoadScriptEngine(generator);
            generator.LoadString("TypeError");
            generator.LoadString("The new operator requires a function, found a '{0}' instead");
            generator.LoadInt32(1);
            generator.NewArray(typeof(object));
            generator.Duplicate();
            generator.LoadInt32(0);
            generator.LoadVariable(targetValue);
            generator.Call(ReflectionHelpers.TypeUtilities_TypeOf);
            generator.StoreArrayElement(typeof(object));
            generator.Call(ReflectionHelpers.String_Format);
            generator.LoadInt32(optimizationInfo.SourceSpan.StartLine);
            generator.LoadStringOrNull(optimizationInfo.Source.Path);
            generator.LoadStringOrNull(optimizationInfo.FunctionName);
            generator.NewObject(ReflectionHelpers.JavaScriptException_Constructor_Error);
            generator.Throw();
            generator.DefineLabelPosition(endOfTypeCheck);
            generator.ReleaseTemporaryVariable(targetValue);

            if (operand is FunctionCallExpression)
            {
                // Emit an array containing the function arguments.
                ((FunctionCallExpression)operand).GenerateArgumentsArray(generator, optimizationInfo);
            }
            else
            {
                // Emit an empty array.
                generator.LoadInt32(0);
                generator.NewArray(typeof(object));
            }

            // Call FunctionInstance.ConstructLateBound(argumentValues)
            generator.Call(ReflectionHelpers.FunctionInstance_ConstructLateBound);
        }
        /// <summary>
        /// Generates an array containing the argument values for a tagged template literal.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        /// <param name="templateLiteral"> The template literal expression containing the parameter
        /// values. </param>
        internal void GenerateTemplateArgumentsArray(ILGenerator generator, OptimizationInfo optimizationInfo, TemplateLiteralExpression templateLiteral)
        {
            // Generate an array containing the value of each argument.
            generator.LoadInt32(templateLiteral.Values.Count + 1);
            generator.NewArray(typeof(object));

            // Load the first parameter.
            generator.Duplicate();
            generator.LoadInt32(0);

            // The first parameter to the tag function is an array of strings.
            var stringsExpression = new List<Expression>(templateLiteral.Strings.Count);
            foreach (var templateString in templateLiteral.Strings)
            {
                stringsExpression.Add(new LiteralExpression(templateString));
            }
            new LiteralExpression(stringsExpression).GenerateCode(generator, optimizationInfo);
            generator.Duplicate();

            // Now we need the name of the property.
            generator.LoadString("raw");

            // Now generate an array of raw strings.
            var rawStringsExpression = new List<Expression>(templateLiteral.RawStrings.Count);
            foreach (var rawString in templateLiteral.RawStrings)
            {
                rawStringsExpression.Add(new LiteralExpression(rawString));
            }
            new LiteralExpression(rawStringsExpression).GenerateCode(generator, optimizationInfo);

            // Freeze array by calling ObjectInstance Freeze(ObjectInstance).
            generator.CallStatic(ReflectionHelpers.ObjectConstructor_Freeze);

            // Now store the raw strings as a property of the base strings array.
            generator.LoadBoolean(optimizationInfo.StrictMode);
            generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_Object);

            // Freeze array by calling ObjectInstance Freeze(ObjectInstance).
            generator.CallStatic(ReflectionHelpers.ObjectConstructor_Freeze);

            // Store in the array.
            generator.StoreArrayElement(typeof(object));

            // Values are passed as subsequent parameters.
            for (int i = 0; i < templateLiteral.Values.Count; i++)
            {
                generator.Duplicate();
                generator.LoadInt32(i + 1);
                templateLiteral.Values[i].GenerateCode(generator, optimizationInfo);
                EmitConversion.ToAny(generator, templateLiteral.Values[i].ResultType);
                generator.StoreArrayElement(typeof(object));
            }
        }
        /// <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)
        {
            // This code is only used for untagged template literals.
            // Tagged template literals are handled by FunctionCallExpression.

            // Load the values array onto the stack.
            generator.LoadInt32(this.Strings.Count + this.Values.Count);
            generator.NewArray(typeof(string));
            for (int i = 0; i < this.Strings.Count; i++)
            {
                // Operands for StoreArrayElement() are: an array (string[]), index (int), value (string).

                // Store the string.
                generator.Duplicate();
                generator.LoadInt32(i * 2);
                generator.LoadString(this.Strings[i]);
                generator.StoreArrayElement(typeof(string));

                if (i == this.Strings.Count - 1)
                    break;

                // Store the value.
                generator.Duplicate();
                generator.LoadInt32(i * 2 + 1);
                this.Values[i].GenerateCode(generator, optimizationInfo);
                EmitConversion.ToString(generator, this.Values[i].ResultType);
                generator.StoreArrayElement(typeof(string));
            }

            // Call String.Concat(string[])
            generator.CallStatic(ReflectionHelpers.String_Concat);
        }
        /// <summary>
        /// Generates a method that does type conversion and calls the bound method.
        /// </summary>
        /// <param name="generator"> The ILGenerator used to output the body of the method. </param>
        /// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param>
        /// <returns> A delegate that does type conversion and calls the method represented by this
        /// object. </returns>
        protected override void GenerateStub(ILGenerator generator, int argumentCount)
        {
            // Determine the methods that have the correct number of arguments.
            var candidateMethods = new List<BinderMethod>();
            foreach (var candidateMethod in this.targetMethods)
            {
                if (candidateMethod.IsArgumentCountCompatible(argumentCount) == true)
                    candidateMethods.Add(candidateMethod);
            }

            // Zero candidates means no overload had the correct number of arguments.
            if (candidateMethods.Count == 0)
            {
                EmitHelpers.EmitThrow(generator, "TypeError", string.Format("No overload for method '{0}' takes {1} arguments", this.Name, argumentCount));
                EmitHelpers.EmitDefaultValue(generator, PrimitiveType.Any);
                generator.Complete();
                return;
            }

            // Select the method to call at run time.
            generator.LoadInt32(candidateMethods.Count);
            generator.NewArray(typeof(RuntimeMethodHandle));
            for (int i = 0; i < candidateMethods.Count; i ++)
            {
                generator.Duplicate();
                generator.LoadInt32(i);
                generator.LoadToken(candidateMethods[i]);
                generator.StoreArrayElement(typeof(RuntimeMethodHandle));
            }
            generator.LoadArgument(0);
            generator.LoadArgument(1);
            generator.LoadArgument(2);
            generator.Call(ReflectionHelpers.BinderUtilities_ResolveOverloads);

            var endOfMethod = generator.CreateLabel();
            for (int i = 0; i < candidateMethods.Count; i++)
            {
                // Check if this is the selected method.
                ILLabel endOfIf = null;
                if (i < candidateMethods.Count - 1)
                {
                    generator.Duplicate();
                    generator.LoadInt32(i);
                    endOfIf = generator.CreateLabel();
                    generator.BranchIfNotEqual(endOfIf);
                }
                generator.Pop();

                var targetMethod = candidateMethods[i];

                // Convert the arguments.
                foreach (var argument in targetMethod.GenerateArguments(generator, argumentCount))
                {
                    // Load the input parameter value.
                    switch (argument.Source)
                    {
                        case BinderArgumentSource.ScriptEngine:
                            generator.LoadArgument(0);
                            break;
                        case BinderArgumentSource.ThisValue:
                            generator.LoadArgument(1);
                            break;
                        case BinderArgumentSource.InputParameter:
                            generator.LoadArgument(2);
                            generator.LoadInt32(argument.InputParameterIndex);
                            generator.LoadArrayElement(typeof(object));
                            break;
                    }

                    // Convert to the target type.
                    EmitConversionToType(generator, argument.Type, convertToAddress: argument.Source == BinderArgumentSource.ThisValue);
                }

                // Call the target method.
                targetMethod.GenerateCall(generator);

                // Convert the return value.
                if (targetMethod.ReturnType == typeof(void))
                    EmitHelpers.EmitUndefined(generator);
                else
                    EmitConversionToObject(generator, targetMethod.ReturnType);

                // Branch to the end of the method if this was the selected method.
                if (endOfIf != null)
                {
                    generator.Branch(endOfMethod);
                    generator.DefineLabelPosition(endOfIf);
                }
            }

            generator.DefineLabelPosition(endOfMethod);
            generator.Complete();
        }
Example #14
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)
        {
            // Generate a new method.
            this.context.GenerateCode();

            // Add the generated method to the nested function list.
            if (optimizationInfo.NestedFunctions == null)
            {
                optimizationInfo.NestedFunctions = new List <GeneratedMethod>();
            }
            optimizationInfo.NestedFunctions.Add(this.context.GeneratedMethod);

            // Add all the nested methods to the parent list.
            if (this.context.GeneratedMethod.Dependencies != null)
            {
                foreach (var nestedFunctionExpression in this.context.GeneratedMethod.Dependencies)
                {
                    optimizationInfo.NestedFunctions.Add(nestedFunctionExpression);
                }
            }

            // Store the generated method in the cache.
            long generatedMethodID = GeneratedMethod.Save(this.context.GeneratedMethod);

            // Create a UserDefinedFunction.

            // prototype
            EmitHelpers.LoadScriptEngine(generator);
            generator.Call(ReflectionHelpers.ScriptEngine_Function);
            generator.Call(ReflectionHelpers.FunctionInstance_InstancePrototype);

            // name
            string prefix = null;

            if (Name.IsGetter)
            {
                prefix = "get ";
            }
            else if (Name.IsSetter)
            {
                prefix = "set ";
            }
            if (Name.HasStaticName)
            {
                generator.LoadString(prefix + Name.StaticName);
            }
            else
            {
                // Compute the name at runtime.
                if (prefix != null)
                {
                    generator.LoadString(prefix);
                }
                Name.ComputedName.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToString(generator, Name.ComputedName.ResultType);
                if (prefix != null)
                {
                    generator.CallStatic(ReflectionHelpers.String_Concat_String_String);
                }
            }

            // argumentNames
            generator.LoadInt32(this.Arguments.Count);
            generator.NewArray(typeof(string));
            for (int i = 0; i < this.Arguments.Count; i++)
            {
                generator.Duplicate();
                generator.LoadInt32(i);
                generator.LoadString(this.Arguments[i].Name);
                generator.StoreArrayElement(typeof(string));
            }

            // scope
            Scope.GenerateReference(generator, optimizationInfo);

            // bodyText
            generator.LoadString(this.BodyText);

            // body
            generator.LoadInt64(generatedMethodID);
            generator.Call(ReflectionHelpers.GeneratedMethod_Load);

            // strictMode
            generator.LoadBoolean(this.context.StrictMode);

            // container
            if (ContainerVariable != null)
            {
                generator.LoadVariable(ContainerVariable);
            }
            else
            {
                generator.LoadNull();
            }

            // CreateFunction(ObjectInstance prototype, string name, IList<string> argumentNames,
            //   RuntimeScope scope, Func<Scope, object, object[], object> body,
            //   bool strictMode, FunctionInstance container)
            generator.CallStatic(ReflectionHelpers.ReflectionHelpers_CreateFunction);
        }
Example #15
0
        /// <summary>
        /// Generates a method that does type conversion and calls the bound method.
        /// </summary>
        /// <param name="generator"> The ILGenerator used to output the body of the method. </param>
        /// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param>
        /// <returns> A delegate that does type conversion and calls the method represented by this
        /// object. </returns>
        protected override void GenerateStub(ILGenerator generator, int argumentCount)
        {
            // Determine the methods that have the correct number of arguments.
            var candidateMethods = new List <BinderMethod>();

            foreach (var candidateMethod in this.targetMethods)
            {
                if (candidateMethod.IsArgumentCountCompatible(argumentCount) == true)
                {
                    candidateMethods.Add(candidateMethod);
                }
            }

            // Zero candidates means no overload had the correct number of arguments.
            if (candidateMethods.Count == 0)
            {
                EmitHelpers.EmitThrow(generator, ErrorType.TypeError, string.Format("No overload for method '{0}' takes {1} arguments", this.Name, argumentCount));
                EmitHelpers.EmitDefaultValue(generator, PrimitiveType.Any);
                generator.Complete();
                return;
            }

            // Select the method to call at run time.
            generator.LoadInt32(candidateMethods.Count);
            generator.NewArray(typeof(RuntimeMethodHandle));
            for (int i = 0; i < candidateMethods.Count; i++)
            {
                generator.Duplicate();
                generator.LoadInt32(i);
                generator.LoadToken(candidateMethods[i]);
                generator.StoreArrayElement(typeof(RuntimeMethodHandle));
            }
            generator.LoadArgument(0);
            generator.LoadArgument(1);
            generator.LoadArgument(2);
            generator.Call(ReflectionHelpers.BinderUtilities_ResolveOverloads);

            var endOfMethod = generator.CreateLabel();

            for (int i = 0; i < candidateMethods.Count; i++)
            {
                // Check if this is the selected method.
                ILLabel endOfIf = null;
                if (i < candidateMethods.Count - 1)
                {
                    generator.Duplicate();
                    generator.LoadInt32(i);
                    endOfIf = generator.CreateLabel();
                    generator.BranchIfNotEqual(endOfIf);
                }
                generator.Pop();

                var targetMethod = candidateMethods[i];

                // Convert the arguments.
                foreach (var argument in targetMethod.GenerateArguments(generator, argumentCount))
                {
                    // Load the input parameter value.
                    switch (argument.Source)
                    {
                    case BinderArgumentSource.ScriptEngine:
                        generator.LoadArgument(0);
                        break;

                    case BinderArgumentSource.ThisValue:
                        generator.LoadArgument(1);
                        break;

                    case BinderArgumentSource.InputParameter:
                        generator.LoadArgument(2);
                        generator.LoadInt32(argument.InputParameterIndex);
                        generator.LoadArrayElement(typeof(object));
                        break;
                    }

                    // Convert to the target type.
                    EmitConversionToType(generator, argument.Type, convertToAddress: argument.Source == BinderArgumentSource.ThisValue);
                }

                // Call the target method.
                targetMethod.GenerateCall(generator);

                // Convert the return value.
                if (targetMethod.ReturnType == typeof(void))
                {
                    EmitHelpers.EmitUndefined(generator);
                }
                else
                {
                    EmitConversionToObject(generator, targetMethod.ReturnType);
                }

                // Branch to the end of the method if this was the selected method.
                if (endOfIf != null)
                {
                    generator.Branch(endOfMethod);
                    generator.DefineLabelPosition(endOfIf);
                }
            }

            generator.DefineLabelPosition(endOfMethod);
            generator.Complete();
        }
        /// <summary>
        /// Generates CIL for the in operator.
        /// </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 GenerateIn(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Emit the left-hand side expression and convert it to a string.
            this.Left.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToString(generator, this.Left.ResultType);

            // Store the left-hand side expression in a temporary variable.
            var temp = generator.CreateTemporaryVariable(typeof(string));
            generator.StoreVariable(temp);

            // Emit the right-hand side expression.
            this.Right.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToAny(generator, this.Right.ResultType);

            // Check the right-hand side is a javascript object - if not, throw an exception.
            generator.IsInstance(typeof(Library.ObjectInstance));
            generator.Duplicate();
            var endOfTypeCheck = generator.CreateLabel();
            generator.BranchIfNotNull(endOfTypeCheck);

            // Throw an nicely formatted exception.
            var rightValue = generator.CreateTemporaryVariable(typeof(object));
            generator.StoreVariable(rightValue);
            EmitHelpers.LoadScriptEngine(generator);
            generator.LoadString("TypeError");
            generator.LoadString("The in operator expected an object, but found '{0}' instead");
            generator.LoadInt32(1);
            generator.NewArray(typeof(object));
            generator.Duplicate();
            generator.LoadInt32(0);
            generator.LoadVariable(rightValue);
            generator.Call(ReflectionHelpers.TypeUtilities_TypeOf);
            generator.StoreArrayElement(typeof(object));
            generator.Call(ReflectionHelpers.String_Format);
            generator.LoadInt32(optimizationInfo.SourceSpan.StartLine);
            generator.LoadStringOrNull(optimizationInfo.Source.Path);
            generator.LoadStringOrNull(optimizationInfo.FunctionName);
            generator.NewObject(ReflectionHelpers.JavaScriptException_Constructor_Error);
            generator.Throw();
            generator.DefineLabelPosition(endOfTypeCheck);
            generator.ReleaseTemporaryVariable(rightValue);

            // Load the left-hand side expression from the temporary variable.
            generator.LoadVariable(temp);

            // Call ObjectInstance.HasProperty(object)
            generator.Call(ReflectionHelpers.ObjectInstance_HasProperty);

            // Allow the temporary variable to be reused.
            generator.ReleaseTemporaryVariable(temp);
        }
Example #17
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)
        {
            // Generate a new method.
            this.context.GenerateCode();

            // Add the generated method to the nested function list.
            if (optimizationInfo.NestedFunctions == null)
            {
                optimizationInfo.NestedFunctions = new List <GeneratedMethod>();
            }
            optimizationInfo.NestedFunctions.Add(this.context.GeneratedMethod);

            // Add all the nested methods to the parent list.
            if (this.context.GeneratedMethod.Dependencies != null)
            {
                foreach (var nestedFunctionExpression in this.context.GeneratedMethod.Dependencies)
                {
                    optimizationInfo.NestedFunctions.Add(nestedFunctionExpression);
                }
            }

            // Store the generated method in the cache.
            long generatedMethodID = GeneratedMethod.Save(this.context.GeneratedMethod);

            // Create a UserDefinedFunction.

            // prototype
            EmitHelpers.LoadScriptEngine(generator);
            generator.Call(ReflectionHelpers.ScriptEngine_Function);
            generator.Call(ReflectionHelpers.FunctionInstance_InstancePrototype);

            // name
            if (this.context.DeclarationType == FunctionDeclarationType.Getter)
            {
                generator.LoadString("get " + this.FunctionName);
            }
            else if (this.context.DeclarationType == FunctionDeclarationType.Setter)
            {
                generator.LoadString("set " + this.FunctionName);
            }
            else
            {
                generator.LoadString(this.FunctionName);
            }

            // argumentNames
            generator.LoadInt32(this.Arguments.Count);
            generator.NewArray(typeof(string));
            for (int i = 0; i < this.Arguments.Count; i++)
            {
                generator.Duplicate();
                generator.LoadInt32(i);
                generator.LoadString(this.Arguments[i].Name);
                generator.StoreArrayElement(typeof(string));
            }

            // scope
            EmitHelpers.LoadScope(generator);

            // bodyText
            generator.LoadString(this.BodyText);

            // body
            generator.LoadInt64(generatedMethodID);
            generator.Call(ReflectionHelpers.GeneratedMethod_Load);

            // strictMode
            generator.LoadBoolean(this.context.StrictMode);

            // new UserDefinedFunction(ObjectInstance prototype, string name, IList<string> argumentNames, DeclarativeScope scope, Func<Scope, object, object[], object> body, bool strictMode)
            generator.NewObject(ReflectionHelpers.UserDefinedFunction_Constructor);
        }
        /// <summary>
        /// Generates an array containing the argument values.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        internal void GenerateArgumentsArray(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Emit the arguments.  The arguments operand can be non-existant, a single expression,
            // or a comma-delimited list.
            if (this.OperandCount < 2)
            {
                // No parameters passed.  Create an empty array.
                generator.LoadInt32(0);
                generator.NewArray(typeof(object));
            }
            else
            {
                // One or more arguments.
                IList<Expression> arguments;
                var argumentsOperand = this.GetRawOperand(1);
                if (argumentsOperand is ListExpression)
                {
                    // Multiple parameters were passed to the function.
                    arguments = ((ListExpression)argumentsOperand).Items;
                }
                else
                {
                    // A single parameter was passed to the function.
                    arguments = new List<Expression>(1) { argumentsOperand };
                }

                // Generate an array containing the value of each argument.
                generator.LoadInt32(arguments.Count);
                generator.NewArray(typeof(object));
                for (int i = 0; i < arguments.Count; i++)
                {
                    generator.Duplicate();
                    generator.LoadInt32(i);
                    arguments[i].GenerateCode(generator, optimizationInfo);
                    EmitConversion.ToAny(generator, arguments[i].ResultType);
                    generator.StoreArrayElement(typeof(object));
                }
            }
        }
        /// <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)
        {
            // Generate a new method.
            this.context.GenerateCode();

            // Add the generated method to the nested function list.
            if (optimizationInfo.NestedFunctions == null)
                optimizationInfo.NestedFunctions = new List<GeneratedMethod>();
            optimizationInfo.NestedFunctions.Add(this.context.GeneratedMethod);

            // Add all the nested methods to the parent list.
            if (this.context.GeneratedMethod.Dependencies != null)
            {
                foreach (var nestedFunctionExpression in this.context.GeneratedMethod.Dependencies)
                    optimizationInfo.NestedFunctions.Add(nestedFunctionExpression);
            }

            // Store the generated method in the cache.
            long generatedMethodID = GeneratedMethod.Save(this.context.GeneratedMethod);

            // Create a UserDefinedFunction.

            // prototype
            EmitHelpers.LoadScriptEngine(generator);
            generator.Call(ReflectionHelpers.ScriptEngine_Function);
            generator.Call(ReflectionHelpers.FunctionInstance_InstancePrototype);

            // name
            generator.LoadString(this.FunctionName);

            // argumentNames
            generator.LoadInt32(this.ArgumentNames.Count);
            generator.NewArray(typeof(string));
            for (int i = 0; i < this.ArgumentNames.Count; i++)
            {
                generator.Duplicate();
                generator.LoadInt32(i);
                generator.LoadString(this.ArgumentNames[i]);
                generator.StoreArrayElement(typeof(string));
            }

            // scope
            EmitHelpers.LoadScope(generator);

            // bodyText
            generator.LoadString(this.BodyText);

            // body
            generator.LoadInt64(generatedMethodID);
            generator.Call(ReflectionHelpers.GeneratedMethod_Load);


            // strictMode
            generator.LoadBoolean(this.context.StrictMode);

            // new UserDefinedFunction(ObjectInstance prototype, string name, IList<string> argumentNames, DeclarativeScope scope, Func<Scope, object, object[], object> body, bool strictMode)
            generator.NewObject(ReflectionHelpers.UserDefinedFunction_Constructor);
        }
Example #20
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)
        {
            // Note: we use GetRawOperand() so that grouping operators are not ignored.
            var operand = this.GetRawOperand(0);

            // There is only one operand, and it can be either a reference or a function call.
            // We need to split the operand into a function and some arguments.
            // If the operand is a reference, it is equivalent to a function call with no arguments.
            if (operand is FunctionCallExpression)
            {
                // Emit the function instance first.
                var function = ((FunctionCallExpression)operand).Target;
                function.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToAny(generator, function.ResultType);
            }
            else
            {
                // Emit the function instance first.
                operand.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToAny(generator, operand.ResultType);
            }

            // Check the object really is a function - if not, throw an exception.
            generator.IsInstance(typeof(Library.FunctionInstance));
            generator.Duplicate();
            var endOfTypeCheck = generator.CreateLabel();

            generator.BranchIfNotNull(endOfTypeCheck);

            // Throw an nicely formatted exception.
            var targetValue = generator.CreateTemporaryVariable(typeof(object));

            generator.StoreVariable(targetValue);
            EmitHelpers.LoadScriptEngine(generator);
            generator.LoadString("TypeError");
            generator.LoadString("The new operator requires a function, found a '{0}' instead");
            generator.LoadInt32(1);
            generator.NewArray(typeof(object));
            generator.Duplicate();
            generator.LoadInt32(0);
            generator.LoadVariable(targetValue);
            generator.Call(ReflectionHelpers.TypeUtilities_TypeOf);
            generator.StoreArrayElement(typeof(object));
            generator.Call(ReflectionHelpers.String_Format);
            generator.NewObject(ReflectionHelpers.JavaScriptException_Constructor_Error);
            generator.Throw();
            generator.DefineLabelPosition(endOfTypeCheck);
            generator.ReleaseTemporaryVariable(targetValue);

            if (operand is FunctionCallExpression)
            {
                // Emit an array containing the function arguments.
                ((FunctionCallExpression)operand).GenerateArgumentsArray(generator, optimizationInfo);
            }
            else
            {
                // Emit an empty array.
                generator.LoadInt32(0);
                generator.NewArray(typeof(object));
            }

            // Call FunctionInstance.ConstructLateBound(argumentValues)
            generator.Call(ReflectionHelpers.FunctionInstance_ConstructLateBound);
        }
        /// <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)
        {
            // Literals cannot have side-effects so if a return value is not expected then generate
            // nothing.
            //if (optimizationInfo.SuppressReturnValue == true)
            //    return;

            if (this.Value is int)
            {
                generator.LoadInt32((int)this.Value);
            }
            else if (this.Value is double)
            {
                generator.LoadDouble((double)this.Value);
            }
            else if (this.Value is string)
            {
                generator.LoadString((string)this.Value);
            }
            else if (this.Value is bool)
            {
                generator.LoadBoolean((bool)this.Value);
            }
            else if (this.Value is RegularExpressionLiteral)
            {
                // RegExp
                var sharedRegExpVariable = optimizationInfo.GetRegExpVariable(generator, (RegularExpressionLiteral)this.Value);
                var label1 = generator.CreateLabel();
                var label2 = generator.CreateLabel();

                // if (sharedRegExp == null) {
                generator.LoadVariable(sharedRegExpVariable);
                generator.LoadNull();
                generator.BranchIfNotEqual(label1);

                // sharedRegExp = Global.RegExp.Construct(source, flags)
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_RegExp);
                generator.LoadString(((RegularExpressionLiteral)this.Value).Pattern);
                generator.LoadString(((RegularExpressionLiteral)this.Value).Flags);
                generator.Call(ReflectionHelpers.RegExp_Construct);
                generator.Duplicate();
                generator.StoreVariable(sharedRegExpVariable);

                // } else {
                generator.Branch(label2);
                generator.DefineLabelPosition(label1);

                // Global.RegExp.Construct(sharedRegExp, flags)
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_RegExp);
                generator.LoadVariable(sharedRegExpVariable);
                generator.LoadNull();
                generator.Call(ReflectionHelpers.RegExp_Construct);

                // }
                generator.DefineLabelPosition(label2);
            }
            else if (this.Value == Null.Value)
            {
                // Null.
                EmitHelpers.EmitNull(generator);
            }
            else if (this.Value == Undefined.Value)
            {
                // Undefined.
                EmitHelpers.EmitUndefined(generator);
            }
            else if (this.Value is List <Expression> )
            {
                // Construct an array literal.
                var arrayLiteral = (List <Expression>) this.Value;

                // Operands for ArrayConstructor.New() are: an ArrayConstructor instance (ArrayConstructor), an array (object[])
                // ArrayConstructor
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Array);

                // object[]
                generator.LoadInt32(arrayLiteral.Count);
                generator.NewArray(typeof(object));
                for (int i = 0; i < arrayLiteral.Count; i++)
                {
                    // Operands for StoreArrayElement() are: an array (object[]), index (int), value (object).
                    // Array
                    generator.Duplicate();

                    // Index
                    generator.LoadInt32(i);

                    // Value
                    var elementExpression = arrayLiteral[i];
                    if (elementExpression == null)
                    {
                        generator.LoadNull();
                    }
                    else
                    {
                        elementExpression.GenerateCode(generator, optimizationInfo);
                        EmitConversion.ToAny(generator, elementExpression.ResultType);
                    }

                    // Store the element value.
                    generator.StoreArrayElement(typeof(object));
                }

                // ArrayConstructor.New(object[])
                generator.Call(ReflectionHelpers.Array_New);
            }
            else if (this.Value is Dictionary <string, object> )
            {
                // This is an object literal.
                var properties = (Dictionary <string, object>) this.Value;

                // Create a new object.
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Object);
                generator.Call(ReflectionHelpers.Object_Construct);

                foreach (var keyValuePair in properties)
                {
                    string propertyName  = keyValuePair.Key;
                    object propertyValue = keyValuePair.Value;

                    generator.Duplicate();
                    generator.LoadString(propertyName);
                    if (propertyValue is Expression)
                    {
                        // Add a new property to the object.
                        var dataPropertyValue = (Expression)propertyValue;
                        dataPropertyValue.GenerateCode(generator, optimizationInfo);
                        // Support the inferred function displayName property.
                        if (dataPropertyValue is FunctionExpression)
                        {
                            ((FunctionExpression)dataPropertyValue).GenerateDisplayName(generator, optimizationInfo, propertyName, false);
                        }
                        EmitConversion.ToAny(generator, dataPropertyValue.ResultType);
                        generator.LoadBoolean(optimizationInfo.StrictMode);
                        generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_String);
                    }
                    else if (propertyValue is Parser.ObjectLiteralAccessor)
                    {
                        // Add a new getter/setter to the object.
                        var accessorValue = (Parser.ObjectLiteralAccessor)propertyValue;
                        if (accessorValue.Getter != null)
                        {
                            accessorValue.Getter.GenerateCode(generator, optimizationInfo);
                            // Support the inferred function displayName property.
                            accessorValue.Getter.GenerateDisplayName(generator, optimizationInfo, "get " + propertyName, true);
                            EmitConversion.ToAny(generator, accessorValue.Getter.ResultType);
                        }
                        else
                        {
                            generator.LoadNull();
                        }
                        if (accessorValue.Setter != null)
                        {
                            accessorValue.Setter.GenerateCode(generator, optimizationInfo);
                            // Support the inferred function displayName property.
                            accessorValue.Setter.GenerateDisplayName(generator, optimizationInfo, "set " + propertyName, true);
                            EmitConversion.ToAny(generator, accessorValue.Setter.ResultType);
                        }
                        else
                        {
                            generator.LoadNull();
                        }
                        generator.LoadInt32((int)Library.PropertyAttributes.FullAccess);
                        generator.NewObject(ReflectionHelpers.PropertyDescriptor_Constructor3);
                        generator.LoadBoolean(false);
                        generator.Call(ReflectionHelpers.ObjectInstance_DefineProperty);
                        generator.Pop();
                    }
                    else
                    {
                        throw new InvalidOperationException("Invalid property value type in object literal.");
                    }
                }
            }
            else
            {
                throw new NotImplementedException("Unknown literal type.");
            }
        }
        /// <summary>
        /// Generates an array containing the argument values for a tagged template literal.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        /// <param name="templateLiteral"> The template literal expression containing the parameter
        /// values. </param>
        internal void GenerateTemplateArgumentsArray(ILGenerator generator, OptimizationInfo optimizationInfo, TemplateLiteralExpression templateLiteral)
        {
            // Generate an array containing the value of each argument.
            generator.LoadInt32(templateLiteral.Values.Count + 1);
            generator.NewArray(typeof(object));

            // Load the first parameter.
            generator.Duplicate();
            generator.LoadInt32(0);

            // Generate a unique integer that is used as the cache key.
            int callSiteId = System.Threading.Interlocked.Increment(ref templateCallSiteId);

            // Call GetCachedTemplateStringsArray(ScriptEngine engine, int callSiteId)
            EmitHelpers.LoadScriptEngine(generator);
            generator.LoadInt32(callSiteId);
            generator.CallStatic(ReflectionHelpers.ReflectionHelpers_GetCachedTemplateStringsArray);

            // If that's null, do it the long way.
            var afterCreateTemplateStringsArray = generator.CreateLabel();

            generator.Duplicate();
            generator.BranchIfNotNull(afterCreateTemplateStringsArray);
            generator.Pop();

            // Start emitting arguments for CreateTemplateStringsArray.
            EmitHelpers.LoadScriptEngine(generator);

            // int callSiteId
            generator.LoadInt32(callSiteId);

            // string[] strings
            generator.LoadInt32(templateLiteral.Strings.Count);
            generator.NewArray(typeof(string));
            for (int i = 0; i < templateLiteral.Strings.Count; i++)
            {
                // strings[i] = templateLiteral.Strings[i]
                generator.Duplicate();
                generator.LoadInt32(i);
                generator.LoadString(templateLiteral.Strings[i]);
                generator.StoreArrayElement(typeof(string));
            }

            // string[] raw
            generator.LoadInt32(templateLiteral.RawStrings.Count);
            generator.NewArray(typeof(string));
            for (int i = 0; i < templateLiteral.RawStrings.Count; i++)
            {
                // raw[i] = templateLiteral.RawStrings[i]
                generator.Duplicate();
                generator.LoadInt32(i);
                generator.LoadString(templateLiteral.RawStrings[i]);
                generator.StoreArrayElement(typeof(string));
            }

            // CreateTemplateStringsArray(ScriptEngine engine, int callSiteId, object[] strings, object[] rawStrings)
            generator.CallStatic(ReflectionHelpers.ReflectionHelpers_CreateTemplateStringsArray);
            generator.DefineLabelPosition(afterCreateTemplateStringsArray);

            // Store in the array.
            generator.StoreArrayElement(typeof(object));

            // Values are passed as subsequent parameters.
            for (int i = 0; i < templateLiteral.Values.Count; i++)
            {
                generator.Duplicate();
                generator.LoadInt32(i + 1);
                templateLiteral.Values[i].GenerateCode(generator, optimizationInfo);
                EmitConversion.ToAny(generator, templateLiteral.Values[i].ResultType);
                generator.StoreArrayElement(typeof(object));
            }
        }
Example #23
0
        /// <summary>
        /// Generates code that creates a new scope.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        internal void GenerateScopeCreation(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Make sure we don't generate the scope twice.
            if (GenerateScopeCreationWasCalled)
            {
                return;
            }
            GenerateScopeCreationWasCalled = true;

            // We can optimize this away if there are zero variables declared in the scope,
            // UNLESS it's a with scope (as then we need something to bind to).
            if (this.variables.Count == 0 && Type != ScopeType.With)
            {
                return;
            }

            // If there is no eval(), no arguments usage and no nested functions, then we can use
            // IL variables instead of using RuntimeScope.
            if ((Type == ScopeType.TopLevelFunction || Type == ScopeType.Block) &&
                optimizationInfo.OptimizeDeclarativeScopes)
            {
                foreach (var variable in this.variables.Values)
                {
                    variable.Store = generator.DeclareVariable(variable.Type, variable.Name);
                    if (variable.Type == PrimitiveType.Any)
                    {
                        generator.LoadNull();
                        generator.StoreVariable(variable.Store);
                    }
                }
                return;
            }

            // The fallback: use RuntimeScope.
            EmitHelpers.LoadExecutionContext(generator);

            // parentScope
            if (ParentScope != null)
            {
                ParentScope.GenerateReference(generator, optimizationInfo);
            }
            else
            {
                generator.LoadNull();
            }

            var varList   = new List <DeclaredVariable>();
            var letList   = new List <DeclaredVariable>();
            var constList = new List <DeclaredVariable>();

            foreach (var variable in this.variables.Values)
            {
                if (variable.Keyword == KeywordToken.Var)
                {
                    varList.Add(variable);
                }
                else if (variable.Keyword == KeywordToken.Const)
                {
                    constList.Add(variable);
                }
                else
                {
                    letList.Add(variable);
                }
            }
            varList.Sort((a, b) => a.Index - b.Index);
            letList.Sort((a, b) => a.Index - b.Index);
            constList.Sort((a, b) => a.Index - b.Index);
            int i;

            // scopeType
            generator.LoadEnumValue(Type);

            // varNames
            if (varList.Count == 0)
            {
                generator.LoadNull();
            }
            else
            {
                generator.LoadInt32(varList.Count);
                generator.NewArray(typeof(string));
                i = 0;
                foreach (var variable in varList)
                {
                    generator.Duplicate();
                    generator.LoadInt32(i++);
                    generator.LoadString(variable.Name);
                    generator.StoreArrayElement(typeof(string));
                }
            }

            // letNames
            if (letList.Count == 0)
            {
                generator.LoadNull();
            }
            else
            {
                generator.LoadInt32(letList.Count);
                generator.NewArray(typeof(string));
                i = 0;
                foreach (var variable in letList)
                {
                    generator.Duplicate();
                    generator.LoadInt32(i++);
                    generator.LoadString(variable.Name);
                    generator.StoreArrayElement(typeof(string));
                }
            }

            // constNames
            if (constList.Count == 0)
            {
                generator.LoadNull();
            }
            else
            {
                generator.LoadInt32(constList.Count);
                generator.NewArray(typeof(string));
                i = 0;
                foreach (var variable in constList)
                {
                    generator.Duplicate();
                    generator.LoadInt32(i++);
                    generator.LoadString(variable.Name);
                    generator.StoreArrayElement(typeof(string));
                }
            }

            // executionContext.CreateRuntimeScope(parentScope, varNames, letNames, constNames)
            generator.Call(ReflectionHelpers.ExecutionContext_CreateRuntimeScope);

            // Store the RuntimeScope instance in a variable.
            GeneratedRuntimeScope = generator.DeclareVariable(typeof(RuntimeScope), "scope");
            generator.StoreVariable(GeneratedRuntimeScope);
        }
        /// <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)
        {
            // Literals cannot have side-effects so if a return value is not expected then generate
            // nothing.
            //if (optimizationInfo.SuppressReturnValue == true) 
            //    return;

            if (this.Value is int)
                generator.LoadInt32((int)this.Value);
            else if (this.Value is double)
                generator.LoadDouble((double)this.Value);
            else if (this.Value is string)
                generator.LoadString((string)this.Value);
            else if (this.Value is bool)
                generator.LoadBoolean((bool)this.Value);
            else if (this.Value is RegularExpressionLiteral)
            {
                // RegExp
                var sharedRegExpVariable = optimizationInfo.GetRegExpVariable(generator, (RegularExpressionLiteral)this.Value);
                var label1 = generator.CreateLabel();
                var label2 = generator.CreateLabel();

                // if (sharedRegExp == null) {
                generator.LoadVariable(sharedRegExpVariable);
                generator.LoadNull();
                generator.BranchIfNotEqual(label1);

                // sharedRegExp = Global.RegExp.Construct(source, flags)
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_RegExp);
                generator.LoadString(((RegularExpressionLiteral)this.Value).Pattern);
                generator.LoadString(((RegularExpressionLiteral)this.Value).Flags);
                generator.Call(ReflectionHelpers.RegExp_Construct);
                generator.Duplicate();
                generator.StoreVariable(sharedRegExpVariable);

                // } else {
                generator.Branch(label2);
                generator.DefineLabelPosition(label1);

                // Global.RegExp.Construct(sharedRegExp, flags)
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_RegExp);
                generator.LoadVariable(sharedRegExpVariable);
                generator.LoadNull();
                generator.Call(ReflectionHelpers.RegExp_Construct);

                // }
                generator.DefineLabelPosition(label2);
            }
            else if (this.Value == Null.Value)
            {
                // Null.
                EmitHelpers.EmitNull(generator);
            }
            else if (this.Value == Undefined.Value)
            {
                // Undefined.
                EmitHelpers.EmitUndefined(generator);
            }
            else if (this.Value is List<Expression>)
            {
                // Construct an array literal.
                var arrayLiteral = (List<Expression>)this.Value;

                // Operands for ArrayConstructor.New() are: an ArrayConstructor instance (ArrayConstructor), an array (object[])
                // ArrayConstructor
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Array);

                // object[]
                generator.LoadInt32(arrayLiteral.Count);
                generator.NewArray(typeof(object));
                for (int i = 0; i < arrayLiteral.Count; i ++)
                {
                    // Operands for StoreArrayElement() are: an array (object[]), index (int), value (object).
                    // Array
                    generator.Duplicate();

                    // Index
                    generator.LoadInt32(i);

                    // Value
                    var elementExpression = arrayLiteral[i];
                    if (elementExpression == null)
                        generator.LoadNull();
                    else
                    {
                        elementExpression.GenerateCode(generator, optimizationInfo);
                        EmitConversion.ToAny(generator, elementExpression.ResultType);
                    }

                    // Store the element value.
                    generator.StoreArrayElement(typeof(object));
                }

                // ArrayConstructor.New(object[])
                generator.Call(ReflectionHelpers.Array_New);
            }
            else if (this.Value is Dictionary<string, object>)
            {
                // This is an object literal.
                var properties = (Dictionary<string, object>)this.Value;

                // Create a new object.
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Object);
                generator.Call(ReflectionHelpers.Object_Construct);

                foreach (var keyValuePair in properties)
                {
                    string propertyName = keyValuePair.Key;
                    object propertyValue = keyValuePair.Value;

                    generator.Duplicate();
                    generator.LoadString(propertyName);
                    if (propertyValue is Expression)
                    {
                        // Add a new property to the object.
                        var dataPropertyValue = (Expression)propertyValue;
                        dataPropertyValue.GenerateCode(generator, optimizationInfo);
                        // Support the inferred function displayName property.
                        if (dataPropertyValue is FunctionExpression)
                            ((FunctionExpression)dataPropertyValue).GenerateDisplayName(generator, optimizationInfo, propertyName, false);
                        EmitConversion.ToAny(generator, dataPropertyValue.ResultType);
                        generator.LoadBoolean(optimizationInfo.StrictMode);
                        generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_String);
                    }
                    else if (propertyValue is Parser.ObjectLiteralAccessor)
                    {
                        // Add a new getter/setter to the object.
                        var accessorValue = (Parser.ObjectLiteralAccessor)propertyValue;
                        if (accessorValue.Getter != null)
                        {
                            accessorValue.Getter.GenerateCode(generator, optimizationInfo);
                            // Support the inferred function displayName property.
                            accessorValue.Getter.GenerateDisplayName(generator, optimizationInfo, "get " + propertyName, true);
                            EmitConversion.ToAny(generator, accessorValue.Getter.ResultType);
                        }
                        else
                            generator.LoadNull();
                        if (accessorValue.Setter != null)
                        {
                            accessorValue.Setter.GenerateCode(generator, optimizationInfo);
                            // Support the inferred function displayName property.
                            accessorValue.Setter.GenerateDisplayName(generator, optimizationInfo, "set " + propertyName, true);
                            EmitConversion.ToAny(generator, accessorValue.Setter.ResultType);
                        }
                        else
                            generator.LoadNull();
                        generator.LoadInt32((int)Library.PropertyAttributes.FullAccess);
                        generator.NewObject(ReflectionHelpers.PropertyDescriptor_Constructor3);
                        generator.LoadBoolean(false);
                        generator.Call(ReflectionHelpers.ObjectInstance_DefineProperty);
                        generator.Pop();
                    }
                    else
                        throw new InvalidOperationException("Invalid property value type in object literal.");
                }
            }
            else
                throw new NotImplementedException("Unknown literal type.");
        }
        /// <summary>
        /// Generates code that creates a new scope.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        internal override void GenerateScopeCreation(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Allocate storage for each variable if the declarative scope object has been optimized away.
            if (optimizationInfo.OptimizeDeclarativeScopes == false)
            {

                // Create a new declarative scope.
            
                // parentScope
                EmitHelpers.LoadScope(generator);

                // declaredVariableNames
                generator.LoadInt32(this.DeclaredVariableCount);
                generator.NewArray(typeof(string));
                int i = 0;
                foreach (string variableName in this.DeclaredVariableNames)
                {
                    generator.Duplicate();
                    generator.LoadInt32(i ++);
                    generator.LoadString(variableName);
                    generator.StoreArrayElement(typeof(string));
                }

                // DeclarativeScope.CreateRuntimeScope(parentScope, declaredVariableNames)
                generator.Call(ReflectionHelpers.DeclarativeScope_CreateRuntimeScope);

                // Save the new scope.
                EmitHelpers.StoreScope(generator);

            }
            else
            {

                // The declarative scope can be optimized away entirely.
                foreach (var variable in this.DeclaredVariables)
                {
                    variable.Store = null;
                    variable.Type = PrimitiveType.Any;
                }

                // Indicate the scope was not created.
                this.ExistsAtRuntime = false;

            }
        }
Example #26
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)
        {
            // Literals cannot have side-effects so if a return value is not expected then generate
            // nothing.
            //if (optimizationInfo.SuppressReturnValue == true)
            //    return;

            if (this.Value is int)
                generator.LoadInt32((int)this.Value);
            else if (this.Value is double)
                generator.LoadDouble((double)this.Value);
            else if (this.Value is string)
                generator.LoadString((string)this.Value);
            else if (this.Value is bool)
                generator.LoadBoolean((bool)this.Value);
            else if (this.Value is RegularExpressionLiteral)
            {
                // RegExp
                var sharedRegExpVariable = optimizationInfo.GetRegExpVariable(generator, (RegularExpressionLiteral)this.Value);
                var label1 = generator.CreateLabel();
                var label2 = generator.CreateLabel();

                // if (sharedRegExp == null) {
                generator.LoadVariable(sharedRegExpVariable);
                generator.LoadNull();
                generator.BranchIfNotEqual(label1);

                // sharedRegExp = Global.RegExp.Construct(source, flags)
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_RegExp);
                generator.LoadString(((RegularExpressionLiteral)this.Value).Pattern);
                generator.LoadString(((RegularExpressionLiteral)this.Value).Flags);
                generator.Call(ReflectionHelpers.RegExp_Construct);
                generator.Duplicate();
                generator.StoreVariable(sharedRegExpVariable);

                // } else {
                generator.Branch(label2);
                generator.DefineLabelPosition(label1);

                // Global.RegExp.Construct(sharedRegExp, flags)
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_RegExp);
                generator.LoadVariable(sharedRegExpVariable);
                generator.LoadNull();
                generator.Call(ReflectionHelpers.RegExp_Construct);

                // }
                generator.DefineLabelPosition(label2);
            }
            else if (this.Value == Null.Value)
            {
                // Null.
                EmitHelpers.EmitNull(generator);
            }
            else if (this.Value == Undefined.Value)
            {
                // Undefined.
                EmitHelpers.EmitUndefined(generator);
            }
            else if (this.Value is List<Expression>)
            {
                // Construct an array literal.
                var arrayLiteral = (List<Expression>)this.Value;

                // Operands for ArrayConstructor.New() are: an ArrayConstructor instance (ArrayConstructor), an array (object[])
                // ArrayConstructor
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Array);

                // object[]
                generator.LoadInt32(arrayLiteral.Count);
                generator.NewArray(typeof(object));
                for (int i = 0; i < arrayLiteral.Count; i ++)
                {
                    // Operands for StoreArrayElement() are: an array (object[]), index (int), value (object).
                    // Array
                    generator.Duplicate();

                    // Index
                    generator.LoadInt32(i);

                    // Value
                    var elementExpression = arrayLiteral[i];
                    if (elementExpression == null)
                        generator.LoadNull();
                    else
                    {
                        elementExpression.GenerateCode(generator, optimizationInfo);
                        EmitConversion.ToAny(generator, elementExpression.ResultType);
                    }

                    // Store the element value.
                    generator.StoreArrayElement(typeof(object));
                }

                // ArrayConstructor.New(object[])
                generator.Call(ReflectionHelpers.Array_New);
            }
            else if (this.Value is List<KeyValuePair<Expression, Expression>>)
            {
                // This is an object literal.
                var properties = (List<KeyValuePair<Expression, Expression>>)this.Value;

                // Create a new object.
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Object);
                generator.Call(ReflectionHelpers.Object_Construct);

                foreach (var keyValuePair in properties)
                {
                    Expression propertyName = keyValuePair.Key;
                    Expression propertyValue = keyValuePair.Value;

                    generator.Duplicate();

                    // The key can be a property name or an expression that evaluates to a name.
                    propertyName.GenerateCode(generator, optimizationInfo);
                    EmitConversion.ToPropertyKey(generator, propertyName.ResultType);

                    var functionValue = propertyValue as FunctionExpression;
                    if (functionValue != null && functionValue.DeclarationType == FunctionDeclarationType.Getter)
                    {
                        // Add a getter to the object.
                        functionValue.GenerateCode(generator, optimizationInfo);
                        // Support the inferred function displayName property.
                        if (propertyName is LiteralExpression && ((LiteralExpression)propertyName).Value is string)
                            functionValue.GenerateDisplayName(generator, optimizationInfo, "get " + (string)((LiteralExpression)propertyName).Value, true);
                        generator.Call(ReflectionHelpers.ReflectionHelpers_SetObjectLiteralGetter);
                    }
                    else if(functionValue != null && functionValue.DeclarationType == FunctionDeclarationType.Setter)
                    {
                        // Add a setter to the object.
                        functionValue.GenerateCode(generator, optimizationInfo);
                        // Support the inferred function displayName property.
                        if (propertyName is LiteralExpression && ((LiteralExpression)propertyName).Value is string)
                            functionValue.GenerateDisplayName(generator, optimizationInfo, "set " + (string)((LiteralExpression)propertyName).Value, true);
                        generator.Call(ReflectionHelpers.ReflectionHelpers_SetObjectLiteralSetter);
                    }
                    else
                    {
                        // Add a new property to the object.
                        propertyValue.GenerateCode(generator, optimizationInfo);
                        // Support the inferred function displayName property.
                        if (propertyValue is FunctionExpression && propertyName is LiteralExpression && ((LiteralExpression)propertyName).Value is string)
                            ((FunctionExpression)propertyValue).GenerateDisplayName(generator, optimizationInfo, (string)((LiteralExpression)propertyName).Value, false);
                        EmitConversion.ToAny(generator, propertyValue.ResultType);
                        generator.Call(ReflectionHelpers.ReflectionHelpers_SetObjectLiteralValue);
                    }
                }
            }
            else
                throw new NotImplementedException("Unknown literal type.");
        }