コード例 #1
0
        /// <summary>
        /// Gets the set of types for each argument.
        /// </summary>
        internal Type[] GetArgumentTypes(OptimizationInfo optimizationInfo, bool includeThis, FunctionMethodGenerator methodGenerator)
        {
            // Get the args:
            Expression argumentsOperand = null;

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

                if (argList == null)
                {
                    // Just one (or two, if it includes 'this'):
                    if (includeThis)
                    {
                        return(new Type[] {
                            GetThisType(optimizationInfo, methodGenerator),
                            argumentsOperand.GetResultType(optimizationInfo)
                        });
                    }

                    return(new Type[] {
                        argumentsOperand.GetResultType(optimizationInfo)
                    });
                }

                // Multiple parameters were recieved.
                IList <Expression> arguments = argList.Items;

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

                int count = arguments.Count;

                // Include 'this' if needed:
                if (includeThis)
                {
                    count++;
                }

                // Create the type set:
                Type[] result = new Type[count];

                int start = 0;

                if (includeThis)
                {
                    // Get the 'this' type:
                    start     = 1;
                    result[0] = GetThisType(optimizationInfo, methodGenerator);
                }

                // Get the result type of each one:
                for (int i = start; i < count; i++)
                {
                    result[i] = arguments[i - start].GetResultType(optimizationInfo);
                }

                return(result);
            }

            // Possibly just the 'this' keyword, if it's a UserDef:
            if (includeThis)
            {
                return(new Type[] { GetThisType(optimizationInfo, methodGenerator) });
            }

            // No arguments.
            return(null);
        }
コード例 #2
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);
                }
            }
        }