Ejemplo n.º 1
0
        /// <summary>
        /// Emits the arguments set.
        /// </summary>
        private void EmitArguments(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Get the args:
            IList <Expression> arguments        = null;
            Expression         argumentsOperand = null;

            if (OperandCount > 1)
            {
                argumentsOperand = this.GetRawOperand(1);
                ListExpression argList = argumentsOperand as ListExpression;

                if (argList != null)
                {
                    // Multiple parameters were recieved.
                    arguments = argList.Items;

                    // Set the operand to null so it doesn't try to emit it as a single arg:
                    argumentsOperand = null;
                }
            }

            int  paraCount       = 0;
            int  parameterOffset = 0;
            bool staticMethod    = false;

            System.Reflection.ParameterInfo[] paraSet = null;
            IList <ArgVariable> argsSet = null;


            if (UserDefined == null)
            {
                // - Is the first arg ScriptEngine?
                // - Does it have thisObj / does it want an instance object?
                paraSet = ResolvedMethod.GetParameters();

                paraCount = paraSet.Length;

                staticMethod = ResolvedMethod.IsStatic || ResolvedMethod.IsConstructor;

                if (paraSet.Length > 0)
                {
                    if (paraSet[0].ParameterType == typeof(ScriptEngine))
                    {
                        // Emit an engine reference now:
                        EmitHelpers.LoadEngine(generator);

                        parameterOffset++;
                    }

                    if (paraSet.Length > parameterOffset && paraSet[parameterOffset].Name == "thisObj")
                    {
                        // It's acting like an instance method.
                        parameterOffset++;
                        staticMethod = false;
                    }
                }

                if (!staticMethod)
                {
                    // Generate the 'this' ref:
                    var baseExpression = ((MemberAccessExpression)this.Target).Base;
                    baseExpression.GenerateCode(generator, optimizationInfo);
                }
            }
            else
            {
                // These are always static.
                paraCount = UserDefined.Arguments.Count;

                argsSet = UserDefined.Arguments;

                // Skip 'this' - it's emitted separately:
                parameterOffset = 1;
            }

            // Next, we're matching params starting from parameterOffset with the args,
            // type casting if needed.
            for (int i = parameterOffset; i < paraCount; i++)
            {
                Expression expression   = null;
                object     defaultValue = null;
                Type       paramType    = null;

                if (paraSet == null)
                {
                    // Get the type:
                    paramType = argsSet[i].Type;
                }
                else
                {
                    // Get the parameter info:
                    var param = paraSet[i];

                    // Get the parameters type:
                    paramType = param.ParameterType;

                    // Get the default value:
                    defaultValue = param.RawDefaultValue;

                    // Is it a params array?
                    if (Attribute.IsDefined(param, typeof(ParamArrayAttribute)))
                    {
                        // It's always an array - get the element type:
                        paramType = paramType.GetElementType();

                        // For each of the remaining args..
                        int offset = i - parameterOffset;

                        int argCount = 0;

                        if (arguments != null)
                        {
                            // Get the full count:
                            argCount = arguments.Count;
                        }
                        else if (argumentsOperand != null)
                        {
                            // Just one arg and it's still hanging around.
                            argCount = offset + 1;
                        }

                        // Define an array:
                        generator.LoadInt32(argCount);
                        generator.NewArray(paramType);

                        for (int a = offset; a < argCount; a++)
                        {
                            if (arguments != null)
                            {
                                // One of many args:
                                expression = arguments[a];
                            }
                            else
                            {
                                // Just one arg:
                                expression = argumentsOperand;
                            }

                            generator.Duplicate();
                            generator.LoadInt32(a - offset);
                            expression.GenerateCode(generator, optimizationInfo);
                            Type res = expression.GetResultType(optimizationInfo);

                            EmitConversion.Convert(generator, res, paramType);
                            generator.StoreArrayElement(paramType);
                        }

                        // All done - can't be anymore.
                        break;
                    }
                }

                if (arguments != null && (i - parameterOffset) <= arguments.Count)
                {
                    // Get one of many args:
                    expression = arguments[i - parameterOffset];
                }
                else if (argumentsOperand != null)
                {
                    // Just the one argument.
                    expression = argumentsOperand;

                    // By setting it to null after, it can't get emitted again
                    // (in the event that this method actually accepts >1 args)
                    argumentsOperand = null;
                }

                if (expression == null)
                {
                    // Emit whatever the default is for the parameters type:
                    if (defaultValue != null)
                    {
                        // Emit the default value:
                        EmitHelpers.EmitValue(generator, defaultValue);
                    }
                    else if (paramType.IsValueType)
                    {
                        // E.g. an integer 0
                        EmitHelpers.EmitValue(generator, Activator.CreateInstance(paramType));
                    }
                    else
                    {
                        // Just a null (a real one):
                        generator.LoadNull();
                    }
                }
                else if (expression is TemplateLiteralExpression)
                {
                    // Tagged template literal.
                    TemplateLiteralExpression templateLiteral = (TemplateLiteralExpression)expression;
                    GenerateTemplateArgumentsArray(generator, optimizationInfo, templateLiteral);
                    return;
                }
                else
                {
                    // Output the arg:
                    expression.GenerateCode(generator, optimizationInfo);

                    // Convert:
                    EmitConversion.Convert(generator, expression.GetResultType(optimizationInfo), paramType);
                }
            }
        }
Ejemplo n.º 2
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)
        {
                        #warning change this.

            // 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);

            // 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].GetResultType(optimizationInfo));
                generator.StoreArrayElement(typeof(object));
            }
        }