예제 #1
0
        /// <summary>
        /// Creates a lambda compiler that will compile to a dynamic method
        /// </summary>
        private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda)
        {
            var parameterTypes = GetParameterTypes(lambda).AddFirst(typeof(Closure));

            var method = new DynamicMethod(lambda.Name ?? "lambda_method", lambda.ReturnType, parameterTypes, true);

            _tree   = tree;
            _lambda = lambda;
            _method = method;

            // In a Win8 immersive process user code is not allowed to access non-W8P framework APIs through
            // reflection or RefEmit. Framework code, however, is given an exemption.
            // This is to make sure that user code cannot access non-W8P framework APIs via ExpressionTree.

            // TODO: This API is not available, is there an alternative way to achieve the same.
            // method.ProfileAPICheck = true;

            _ilg = method.GetILGenerator();

            _hasClosureArgument = true;

            // These are populated by AnalyzeTree/VariableBinder
            _scope          = tree.Scopes[lambda];
            _boundConstants = tree.Constants[lambda];

            InitializeMethod();
        }
예제 #2
0
        /// <summary>
        /// Creates a lambda compiler that will compile into the provided Methodbuilder
        /// </summary>
        private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda, MethodBuilder method)
        {
            _hasClosureArgument = tree.Scopes[lambda].NeedsClosure;
            var paramTypes = GetParameterTypes(lambda);

            if (_hasClosureArgument)
            {
                paramTypes = paramTypes.AddFirst(typeof(Closure));
            }

            method.SetReturnType(lambda.ReturnType);
            method.SetParameters(paramTypes);
            var paramNames = lambda.Parameters.Map(p => p.Name);
            // parameters are index from 1, with closure argument we need to skip the first arg
            var startIndex = _hasClosureArgument ? 2 : 1;

            for (int i = 0; i < paramNames.Length; i++)
            {
                method.DefineParameter(i + startIndex, ParameterAttributes.None, paramNames[i]);
            }

            _tree        = tree;
            _lambda      = lambda;
            _typeBuilder = (TypeBuilder)method.DeclaringType;
            _method      = method;

            _ilg = method.GetILGenerator();

            // These are populated by AnalyzeTree/VariableBinder
            _scope          = tree.Scopes[lambda];
            _boundConstants = tree.Constants[lambda];

            InitializeMethod();
        }
예제 #3
0
        /// <summary>
        /// Creates a lambda compiler that will compile into the provided MethodBuilder
        /// </summary>
        private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda, MethodBuilder method)
        {
            var scope = tree.Scopes[lambda];
            var hasClosureArgument = scope.NeedsClosure;

            Type[] paramTypes = GetParameterTypes(lambda, hasClosureArgument ? typeof(Closure) : null);

            method.SetReturnType(lambda.ReturnType);
            method.SetParameters(paramTypes);
            var parameters = lambda.Parameters;
            // parameters are index from 1, with closure argument we need to skip the first arg
            int startIndex = hasClosureArgument ? 2 : 1;

            for (int i = 0, n = parameters.Count; i < n; i++)
            {
                method.DefineParameter(i + startIndex, ParameterAttributes.None, parameters[i].Name);
            }

            _tree               = tree;
            _lambda             = lambda;
            _typeBuilder        = (TypeBuilder)method.DeclaringType;
            _method             = method;
            _hasClosureArgument = hasClosureArgument;

            _ilg = method.GetILGenerator();

            // These are populated by AnalyzeTree/VariableBinder
            _scope          = scope;
            _boundConstants = tree.Constants[lambda];

            InitializeMethod();
        }
예제 #4
0
 /// <summary>
 /// Creates a lambda compiler for an inlined lambda
 /// </summary>
 private LambdaCompiler(LambdaCompiler parent, LambdaExpression lambda)
 {
     _tree               = parent._tree;
     _lambda             = lambda;
     _method             = parent._method;
     _ilg                = parent._ilg;
     _hasClosureArgument = parent._hasClosureArgument;
     _typeBuilder        = parent._typeBuilder;
     _scope              = _tree.Scopes[lambda];
     _boundConstants     = parent._boundConstants;
 }
        protected internal override Expression VisitLambda <T>(Expression <T> node)
        {
            CompilerScope  scope;
            BoundConstants constants;

            this._tree.Scopes[node] = scope = new CompilerScope(node, true);
            this._scopes.Push(scope);
            this._tree.Constants[node] = constants = new BoundConstants();
            this._constants.Push(constants);
            base.Visit(this.MergeScopes(node));
            this._constants.Pop();
            this._scopes.Pop();
            return(node);
        }
예제 #6
0
 /// <summary>
 /// Creates a lambda compiler for an inlined lambda
 /// </summary>
 private LambdaCompiler(
     LambdaCompiler parent,
     LambdaExpression lambda,
     InvocationExpression invocation)
 {
     _tree               = parent._tree;
     _lambda             = lambda;
     _method             = parent._method;
     _ilg                = parent._ilg;
     _hasClosureArgument = parent._hasClosureArgument;
     _typeBuilder        = parent._typeBuilder;
     // inlined scopes are associated with invocation, not with the lambda
     _scope          = _tree.Scopes[invocation];
     _boundConstants = parent._boundConstants;
 }
예제 #7
0
        protected internal override Expression VisitLambda <T>(Expression <T> node)
        {
            var createdScope = new CompilerScope(node, true);

            _tree.Scopes[node] = createdScope;
            _scopes.Push(createdScope);
            var createdConstants = new BoundConstants();

            _tree.Constants[node] = createdConstants;
            _constants.Push(createdConstants);
            Visit(MergeScopes(node));
            _constants.Pop();
            _scopes.Pop();
            return(node);
        }
예제 #8
0
        /// <summary>
        /// Creates a lambda compiler that will compile to a dynamic method
        /// </summary>
        private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda)
        {
            Type[] parameterTypes = GetParameterTypes(lambda, typeof(Closure));

            var method = new DynamicMethod(lambda.Name ?? "lambda_method", lambda.ReturnType, parameterTypes, true);

            _tree   = tree;
            _lambda = lambda;
            _method = method;

            _ilg = method.GetILGenerator();

            _hasClosureArgument = true;

            // These are populated by AnalyzeTree/VariableBinder
            _scope          = tree.Scopes[lambda];
            _boundConstants = tree.Constants[lambda];

            InitializeMethod();
        }
예제 #9
0
        private LambdaCompiler(
            AnalyzedTree tree,
            LambdaExpression lambda,
            TypeBuilder typeBuilder,
            MethodInfo method,
            ILGenerator ilg,
            IList <Type> paramTypes,
            bool dynamicMethod,
            bool emitDebugSymbols)
        {
            ContractUtils.Requires(dynamicMethod || method.IsStatic, "dynamicMethod");
            _tree          = tree;
            _lambda        = lambda;
            _typeBuilder   = typeBuilder;
            _method        = method;
            _paramTypes    = new ReadOnlyCollection <Type>(paramTypes);
            _dynamicMethod = dynamicMethod;

            // These are populated by AnalyzeTree/VariableBinder
            _scope          = tree.Scopes[lambda];
            _boundConstants = tree.Constants[lambda];

            if (!dynamicMethod && _boundConstants.Count > 0)
            {
                throw Error.RtConstRequiresBundDelegate();
            }

            _ilg = new ILGen(ilg);

            Debug.Assert(!emitDebugSymbols || _typeBuilder != null, "emitting debug symbols requires a TypeBuilder");
            _emitDebugSymbols = emitDebugSymbols;

            // See if we can find a return label, so we can emit better IL
            AddReturnLabel(_lambda.Body);

            _boundConstants.EmitCacheConstants(this);
        }