Esempio n. 1
0
 public override void EmitLiteral(MethodContext method, object value)
 {
     switch (System.Runtime.InteropServices.Marshal.SizeOf(Native))
     {
         case 4:
             method.IL.Emit(OpCodes.Ldc_I4, (int)value);
             break;
         case 8:
             method.IL.Emit(OpCodes.Ldc_I8, (long)value);
             break;
         default: throw new NotSupportedException();
     }
 }
Esempio n. 2
0
        protected override void EmitUnaryOperator(MethodContext method, Compiler compiler, ExpressionContext inner, Parse.UnaryExpression expression)
        {
            switch (expression.Operator)
            {
                case Parse.Operator.Exists:
                case Parse.Operator.IsNull:
                case Parse.Operator.Not:
                case Parse.Operator.BitwiseNot:
                    base.EmitUnaryOperator(method, compiler, inner, expression);
                    break;

                default: throw NotSupported(expression);
            }
        }
Esempio n. 3
0
        protected override void EmitBinaryOperator(MethodContext method, Compiler compiler, ExpressionContext left, ExpressionContext right, Parse.BinaryExpression expression)
        {
            switch (expression.Operator)
            {
                case Parse.Operator.Power:
                    var intPower = typeof(Runtime.Runtime).GetMethod("IntPower", new[] { typeof(int), typeof(int) });
                    if (intPower == null)
                        throw new NotSupportedException();
                    left.EmitGet(method);
                    right.EmitGet(method);
                    method.IL.EmitCall(OpCodes.Call, intPower, null);
                    break;

                default:
                    base.EmitBinaryOperator(method, compiler, left, right, expression);
                    break;
            }
        }
Esempio n. 4
0
 protected override void EmitBinaryOperator(MethodContext method, Compiler compiler, ExpressionContext left, ExpressionContext right, Parse.BinaryExpression expression)
 {
     switch (expression.Operator)
     {
         case Parse.Operator.BitwiseAnd:
         case Parse.Operator.BitwiseOr:
         case Parse.Operator.BitwiseXor:
         case Parse.Operator.Xor:
         case Parse.Operator.ShiftLeft:
         case Parse.Operator.ShiftRight:
         case Parse.Operator.And:
         case Parse.Operator.Or:
         case Parse.Operator.Equal:
         case Parse.Operator.NotEqual:
         case Parse.Operator.InclusiveGreater:
         case Parse.Operator.InclusiveLess:
         case Parse.Operator.Greater:
         case Parse.Operator.Less:
             base.EmitBinaryOperator(method, compiler, left, right, expression);
             break;
         default: throw NotSupported(expression);
     }
 }
Esempio n. 5
0
        /// <summary> Overridden to determine what operators a type supports and to change how they are implemented. </summary>
        protected virtual void EmitUnaryOperator(MethodContext method, Compiler compiler, ExpressionContext inner, Parse.UnaryExpression expression)
        {
            var innerType = inner.Type.GetNative(compiler.Emitter);
            inner.EmitGet(method);
            switch (expression.Operator)
            {
                case Parse.Operator.Exists:
                    method.IL.Emit(OpCodes.Pop);
                    method.IL.Emit(OpCodes.Ldc_I4_1);	// true
                    break;
                case Parse.Operator.IsNull:
                    method.IL.Emit(OpCodes.Pop);
                    method.IL.Emit(OpCodes.Ldc_I4_0);	// false
                    break;
                case Parse.Operator.Negate:
                    if (!CallClassOp(method, "op_UnaryNegation", innerType))
                        method.IL.Emit(OpCodes.Neg);
                    break;
                case Parse.Operator.Not:
                    if (!CallClassOp(method, "op_Negation", innerType))
                        method.IL.Emit(OpCodes.Not);
                    break;
                case Parse.Operator.BitwiseNot:
                    if (!CallClassOp(method, "op_OnesComplement", innerType))
                        method.IL.Emit(OpCodes.Not);
                    break;
                case Parse.Operator.Successor:
                    method.IL.Emit(OpCodes.Ldc_I4_1);
                    method.IL.Emit(OpCodes.Add);
                    break;
                case Parse.Operator.Predicessor:
                    method.IL.Emit(OpCodes.Ldc_I4_1);
                    method.IL.Emit(OpCodes.Sub);
                    break;

                default: throw NotSupported(expression);
            }
        }
Esempio n. 6
0
        /// <summary> Overridden to determine what operators a type supports and to change how they are implemented. </summary>
        /// <remarks> Override this rather than CompileBinaryOperator when nothing special is necessary when compiling the right-hand expression. </remarks>
        protected virtual void EmitShortCircuit(MethodContext method, Compiler compiler, Frame frame, ExpressionContext left, ExpressionContext right, Parse.BinaryExpression expression, Type.BaseType typeHint)
        {
            var leftType = left.Type.GetNative(compiler.Emitter);
            var rightType = right.Type.GetNative(compiler.Emitter);
            left.EmitGet(method);
            right.EmitGet(method);
            switch (expression.Operator)
            {
                case Parse.Operator.And:
                    if (!CallClassOp(method, "op_LogicalAnd", leftType, leftType))
                    {
                        var label = method.IL.DefineLabel();
                        method.IL.Emit(OpCodes.Dup);
                        method.IL.Emit(OpCodes.Brfalse_S, label);
                        right.EmitGet(method);
                        method.IL.Emit(OpCodes.And);
                        method.IL.MarkLabel(label);
                    }
                    break;

                case Parse.Operator.Or:
                    if (!CallClassOp(method, "op_LogicalOr", leftType, leftType))
                    {
                        var label = method.IL.DefineLabel();
                        method.IL.Emit(OpCodes.Dup);
                        method.IL.Emit(OpCodes.Brtrue_S, label);
                        right.EmitGet(method);
                        method.IL.Emit(OpCodes.Or);
                        method.IL.MarkLabel(label);
                    }
                    break;

                default: throw new NotSupportedException(String.Format("Operator {0} is not supported.", expression.Operator));
            }
        }
Esempio n. 7
0
        /// <summary> Overridden to determine what operators a type supports and to change how they are implemented. </summary>
        /// <remarks> Override this rather than CompileBinaryOperator when nothing special is necessary when compiling the right-hand expression. </remarks>
        protected virtual void EmitBinaryOperator(MethodContext method, Compiler compiler, ExpressionContext left, ExpressionContext right, Parse.BinaryExpression expression)
        {
            var leftType = left.Type.GetNative(compiler.Emitter);
            var rightType = right.Type.GetNative(compiler.Emitter);
            left.EmitGet(method);
            right.EmitGet(method);
            switch (expression.Operator)
            {
                case Parse.Operator.Addition:
                    if (!CallClassOp(method, "op_Addition", leftType, rightType))
                        method.IL.Emit(OpCodes.Add);
                    break;
                case Parse.Operator.Subtract:
                    if (!CallClassOp(method, "op_Subtraction", leftType, rightType))
                        method.IL.Emit(OpCodes.Sub);
                    break;
                case Parse.Operator.Multiply:
                    if (!CallClassOp(method, "op_Multiply", leftType, rightType))
                        method.IL.Emit(OpCodes.Mul);
                    break;
                case Parse.Operator.Modulo:
                    if (!CallClassOp(method, "op_Modulus", leftType, rightType))
                        method.IL.Emit(OpCodes.Rem);
                    break;
                case Parse.Operator.Divide:
                    if (!CallClassOp(method, "op_Division", leftType, rightType))
                        method.IL.Emit(OpCodes.Div);
                    break;
                case Parse.Operator.Power:
                    var mathPower = typeof(System.Math).GetMethod("Pow", new[] { left.Type.GetNative(compiler.Emitter), right.Type.GetNative(compiler.Emitter) });
                    if (mathPower == null)
                        throw new NotSupportedException();
                    method.IL.EmitCall(OpCodes.Call, mathPower, null);
                    break;
                case Parse.Operator.BitwiseAnd:
                    if (!CallClassOp(method, "op_BitwiseOr", leftType, rightType))
                        method.IL.Emit(OpCodes.And);
                    break;
                case Parse.Operator.BitwiseOr:
                    if (!CallClassOp(method, "op_Addition", leftType, rightType))
                        method.IL.Emit(OpCodes.Or);
                    break;
                case Parse.Operator.BitwiseXor:
                case Parse.Operator.Xor:
                    if (!CallClassOp(method, "op_ExclusiveOr", leftType, rightType))
                        method.IL.Emit(OpCodes.Xor);
                    break;
                case Parse.Operator.ShiftLeft:
                    if (!CallClassOp(method, "op_LeftShift", leftType, rightType))
                        method.IL.Emit(OpCodes.Shl);
                    break;
                case Parse.Operator.ShiftRight:
                    if (!CallClassOp(method, "op_RightShift", leftType, rightType))
                        method.IL.Emit(OpCodes.Shr);
                    break;

                case Parse.Operator.Equal:
                    if (!CallClassOp(method, "op_Equality", leftType, rightType))
                        method.IL.Emit(OpCodes.Ceq);
                    break;
                case Parse.Operator.NotEqual:
                    if (!CallClassOp(method, "op_Inequality", leftType, rightType))
                    {
                        method.IL.Emit(OpCodes.Ceq);
                        method.IL.Emit(OpCodes.Ldc_I4_0);
                        method.IL.Emit(OpCodes.Ceq);
                    }
                    break;
                case Parse.Operator.InclusiveGreater:
                    if (!CallClassOp(method, "op_GreaterThanOrEqual", leftType, rightType))
                    {
                        method.IL.Emit(OpCodes.Clt);
                        method.IL.Emit(OpCodes.Ldc_I4_0);
                        method.IL.Emit(OpCodes.Ceq);
                    }
                    break;
                case Parse.Operator.InclusiveLess:
                    if (!CallClassOp(method, "op_LessThanOrEqual", leftType, rightType))
                    {
                        method.IL.Emit(OpCodes.Cgt);
                        method.IL.Emit(OpCodes.Ldc_I4_0);
                        method.IL.Emit(OpCodes.Ceq);
                    }
                    break;
                case Parse.Operator.Greater:
                    if (!CallClassOp(method, "op_GreaterThan", leftType, rightType))
                        method.IL.Emit(OpCodes.Cgt);
                    break;
                case Parse.Operator.Less:
                    if (!CallClassOp(method, "op_LessThan", leftType, rightType))
                        method.IL.Emit(OpCodes.Clt);
                    break;

                default: throw NotSupported(expression);
            }
        }
Esempio n. 8
0
 /// <summary> Attempt to invoke an operator overload on the left-hand class if there is one. </summary>
 protected bool CallClassOp(MethodContext method, string opName, params System.Type[] types)
 {
     var classOp = types[0].GetMethod(opName, types);
     if (classOp != null)
     {
         method.IL.EmitCall(OpCodes.Call, classOp, null);
         return true;
     }
     return false;
 }
Esempio n. 9
0
 public virtual void EmitLiteral(MethodContext method, object value)
 {
     throw new NotSupportedException();
 }
Esempio n. 10
0
 public System.Type CompleteMain(MethodContext main)
 {
     main.IL.Emit(OpCodes.Ret);
     return ((TypeBuilder)main.Builder.DeclaringType).CreateType();
 }
Esempio n. 11
0
        protected override void EmitBinaryOperator(MethodContext method, Compiler compiler, ExpressionContext left, ExpressionContext right, Parse.BinaryExpression expression)
        {
            switch (expression.Operator)
            {
                case Parse.Operator.Addition:
                    left.EmitGet(method);
                    right.EmitGet(method);
                    method.IL.EmitCall(OpCodes.Call, ReflectionUtility.StringConcat, null);
                    break;

                case Parse.Operator.Equal:
                    base.EmitBinaryOperator(method, compiler, left, right, expression);
                    break;
                case Parse.Operator.NotEqual:
                    left.EmitGet(method);
                    right.EmitGet(method);
                    method.IL.EmitCall(OpCodes.Call, ReflectionUtility.StringCompare, null);
                    method.IL.Emit(OpCodes.Ldc_I4_0);
                    method.IL.Emit(OpCodes.Ceq);
                    // Not
                    method.IL.Emit(OpCodes.Ldc_I4_0);
                    method.IL.Emit(OpCodes.Ceq);
                    break;
                case Parse.Operator.InclusiveGreater:
                    left.EmitGet(method);
                    right.EmitGet(method);
                    method.IL.EmitCall(OpCodes.Call, ReflectionUtility.StringCompare, null);
                    method.IL.Emit(OpCodes.Ldc_I4_0);
                    method.IL.Emit(OpCodes.Clt);
                    // Not
                    method.IL.Emit(OpCodes.Ldc_I4_0);
                    method.IL.Emit(OpCodes.Ceq);
                    break;
                case Parse.Operator.InclusiveLess:
                    left.EmitGet(method);
                    right.EmitGet(method);
                    method.IL.EmitCall(OpCodes.Call, ReflectionUtility.StringCompare, null);
                    method.IL.Emit(OpCodes.Ldc_I4_0);
                    method.IL.Emit(OpCodes.Cgt);
                    // Not
                    method.IL.Emit(OpCodes.Ldc_I4_0);
                    method.IL.Emit(OpCodes.Ceq);
                    break;
                case Parse.Operator.Greater:
                    left.EmitGet(method);
                    right.EmitGet(method);
                    method.IL.EmitCall(OpCodes.Call, ReflectionUtility.StringCompare, null);
                    method.IL.Emit(OpCodes.Ldc_I4_0);
                    method.IL.Emit(OpCodes.Cgt);
                    break;
                case Parse.Operator.Less:
                    left.EmitGet(method);
                    right.EmitGet(method);
                    method.IL.EmitCall(OpCodes.Call, ReflectionUtility.StringCompare, null);
                    method.IL.Emit(OpCodes.Ldc_I4_0);
                    method.IL.Emit(OpCodes.Clt);
                    break;

                default: throw NotSupported(expression);
            }
        }
Esempio n. 12
0
 public override void EmitLiteral(MethodContext method, object value)
 {
     method.IL.Emit(OpCodes.Ldstr, (string)value);
 }
Esempio n. 13
0
        protected override void EmitBinaryOperator(MethodContext method, Compiler compiler, ExpressionContext left, ExpressionContext right, Parse.BinaryExpression expression)
        {
            switch (expression.Operator)
            {
                case Parse.Operator.Equal:
                case Parse.Operator.NotEqual:
                    base.EmitBinaryOperator(method, compiler, left, right, expression);
                    break;

                //// TODO: Tuple union
                //case Parse.Operator.BitwiseOr:

                default: throw NotSupported(expression);
            }
        }
Esempio n. 14
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);
                    }
                );
        }
Esempio n. 15
0
 protected override void EmitUnaryOperator(MethodContext method, Compiler compiler, ExpressionContext inner, Parse.UnaryExpression expression)
 {
     switch (expression.Operator)
     {
         case Parse.Operator.Exists:
             method.IL.EmitCall(OpCodes.Callvirt, typeof(ICollection<>).MakeGenericType(inner.Type.GetNative(compiler.Emitter)).GetProperty("Count").GetGetMethod(), null);
             method.IL.Emit(OpCodes.Ldc_I4_0);
             method.IL.Emit(OpCodes.Cgt);
             break;
         case Parse.Operator.IsNull:
             method.IL.Emit(OpCodes.Pop);
             method.IL.Emit(OpCodes.Ldc_I4_0);
             break;
         default: throw NotSupported(expression);
     }
 }
Esempio n. 16
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);
                    }
                );
        }
Esempio n. 17
0
 // TODO: define operators for TimeSpan
 public override void EmitLiteral(MethodContext method, object value)
 {
     method.IL.Emit(OpCodes.Ldc_I8, ((TimeSpan)value).Ticks);
     method.IL.Emit(OpCodes.Newobj, ReflectionUtility.TimeSpanTicksConstructor);
 }
Esempio n. 18
0
 public override void EmitLiteral(MethodContext method, object value)
 {
     method.IL.Emit(((bool)value) ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
 }