示例#1
0
        // Restriction
        public override ExpressionContext CompileExtractExpression(Compiler compiler, Frame frame, ExpressionContext left, Parse.ExtractExpression expression, BaseType typeHint)
        {
            var memberType = ((NaryType)left.Type).Of;
            var memberNative = left.NativeType ?? memberType.GetNative(compiler.Emitter);

            var local = compiler.AddFrame(frame, expression);

            // Prepare index and value symbols
            var indexSymbol = PrepareValueIndexContext(compiler, left, expression.Condition, memberType, memberNative, local);

            // Compile condition
            var condition = compiler.CompileExpression(local, expression.Condition, SystemTypes.Boolean);
            if (!(condition.Type is BooleanType))
                throw new CompilerException(expression.Condition, CompilerException.Codes.IncorrectType, condition.Type, "Boolean");

            var indexReferenced = compiler.References.ContainsKey(indexSymbol);

            return
                new ExpressionContext
                (
                    expression,
                    left.Type,
                    Compiler.MergeCharacteristics(left.Characteristics, condition.Characteristics),
                    m =>
                    {
                        // Create a new private method for the condition
                        var typeBuilder = (TypeBuilder)m.Builder.DeclaringType;
                        var innerMethod =
                            new MethodContext
                            (
                                typeBuilder.DefineMethod
                                (
                                    "Where" + expression.GetHashCode(),
                                    MethodAttributes.Private | MethodAttributes.Static,
                                    typeof(bool),	// return type
                                    indexReferenced ? new System.Type[] { memberNative, typeof(int) } : new System.Type[] { memberNative }	// param types
                                )
                            );
                        condition.EmitGet(innerMethod);
                        innerMethod.IL.Emit(OpCodes.Ret);

                        left.EmitGet(m);

                        // TODO: Force ordering to left if Set and index is referenced

                        // Instantiate a delegate pointing to the new method
                        m.IL.Emit(OpCodes.Ldnull);				// instance
                        m.IL.Emit(OpCodes.Ldftn, innerMethod.Builder);	// method
                        var funcType =
                            indexReferenced
                                ? System.Linq.Expressions.Expression.GetFuncType(memberNative, typeof(int), typeof(bool))
                                : System.Linq.Expressions.Expression.GetFuncType(memberNative, typeof(bool));
                        m.IL.Emit
                        (
                            OpCodes.Newobj,
                            funcType.GetConstructor(new[] { typeof(object), typeof(IntPtr) })
                        );

                        funcType = indexReferenced ? typeof(Func<ReflectionUtility.T, int, bool>) : typeof(Func<ReflectionUtility.T, bool>);
                        var where = typeof(System.Linq.Enumerable).GetMethodExt("Where", new System.Type[] { typeof(IEnumerable<ReflectionUtility.T>), funcType });
                        where = where.MakeGenericMethod(memberNative);

                        m.IL.EmitCall(OpCodes.Call, where, null);
                    }
                );
        }
示例#2
0
        protected virtual ExpressionContext CompileDereference(Compiler compiler, Frame frame, ExpressionContext left, Parse.BinaryExpression expression, Type.BaseType typeHint)
        {
            var memberType = ((NaryType)left.Type).Of;
            var memberNative = left.NativeType ?? memberType.GetNative(compiler.Emitter);

            var local = compiler.AddFrame(frame, expression);

            // Prepare index and value symbols
            var indexSymbol = PrepareValueIndexContext(compiler, left, expression.Right, memberType, memberNative, local);

            // Compile selection
            var selection = compiler.CompileExpression(local, expression.Right);

            var indexReferenced = compiler.References.ContainsKey(indexSymbol);

            return
                new ExpressionContext
                (
                    expression,
                    new ListType(selection.Type),
                    Compiler.MergeCharacteristics(left.Characteristics, selection.Characteristics),
                    m =>
                    {
                        // Create a new private method for the condition
                        var typeBuilder = (TypeBuilder)m.Builder.DeclaringType;
                        var innerMethod =
                            new MethodContext
                            (
                                typeBuilder.DefineMethod
                                (
                                    "Select" + expression.GetHashCode(),
                                    MethodAttributes.Private | MethodAttributes.Static,
                                    selection.ActualNative(compiler.Emitter),	// temporary return type
                                    indexReferenced ? new System.Type[] { memberNative, typeof(int) } : new System.Type[] { memberNative }	// param types
                                )
                            );
                        selection.EmitGet(innerMethod);
                        innerMethod.IL.Emit(OpCodes.Ret);

                        left.EmitGet(m);

                        // TODO: Force ordering of Left if a set and index is referenced

                        // Instantiate a delegate pointing to the new method
                        m.IL.Emit(OpCodes.Ldnull);				// instance
                        m.IL.Emit(OpCodes.Ldftn, innerMethod.Builder);	// method
                        var funcType =
                            indexReferenced
                                ? System.Linq.Expressions.Expression.GetFuncType(memberNative, typeof(int), innerMethod.Builder.ReturnType)
                                : System.Linq.Expressions.Expression.GetFuncType(memberNative, innerMethod.Builder.ReturnType);
                        m.IL.Emit
                        (
                            OpCodes.Newobj,
                            funcType.GetConstructor(new[] { typeof(object), typeof(IntPtr) })
                        );

                        funcType = indexReferenced ? typeof(Func<ReflectionUtility.T, int, ReflectionUtility.T>) : typeof(Func<ReflectionUtility.T, ReflectionUtility.T>);
                        var select =
                            typeof(Enumerable).GetMethodExt
                            (
                                "Select",
                                new System.Type[] { typeof(IEnumerable<ReflectionUtility.T>), funcType }
                            );
                        select = select.MakeGenericMethod(memberNative, innerMethod.Builder.ReturnType);

                        m.IL.EmitCall(OpCodes.Call, select, null);
                    }
                );
        }