示例#1
0
        public override void Compile(EmitCompilerContext context, EmitIl il)
        {
            switch (Operator)
            {
            case EmitBinaryOperator.Assign:
                ((IEmitReferenceExpression)Left).CompileAssignment(context, il, () => Right.Compile(context, il));
                break;

            case EmitBinaryOperator.BooleanAnd:
                Left.Compile(context, il);
                il.Emit(EmitOpCodes.Dup);

                var andEnd = il.DefineLabel();
                il.Emit(EmitOpCodes.Brfalse, andEnd);
                il.Emit(EmitOpCodes.Pop);

                Right.Compile(context, il);
                il.MarkLabel(andEnd);

                break;

            case EmitBinaryOperator.BooleanOr:
                Left.Compile(context, il);
                il.Emit(EmitOpCodes.Dup);

                var orEnd = il.DefineLabel();
                il.Emit(EmitOpCodes.Brtrue, orEnd);
                il.Emit(EmitOpCodes.Pop);

                Right.Compile(context, il);
                il.MarkLabel(orEnd);

                break;

            default:
                var instruction  = GetOpCode();
                var isInverted   = IsOperatorInverse();
                var isAssignment = IsOperatorAssignment();

                Left.Compile(context, il);
                Right.Compile(context, il);

                il.Emit(instruction);

                if (isInverted)
                {
                    il.Emit(EmitOpCodes.Ldc_I4_0);
                    il.Emit(EmitOpCodes.Ceq);
                }

                if (isAssignment)
                {
                    var local = il.DeclareLocal(typeof(bool));
                    il.Emit(EmitOpCodes.Stloc, local);
                    ((IEmitReferenceExpression)Left).CompileAssignment(context, il, () => il.Emit(EmitOpCodes.Ldloc, local));
                }

                break;
            }
        }
示例#2
0
        public override void Compile(EmitCompilerContext context, EmitIl il)
        {
            Initializer?.Compile(context, il);

            var start = il.DefineLabel();
            var end   = il.DefineLabel();

            il.MarkLabel(start);

            if (Predicate != null)
            {
                Predicate.Compile(context, il);
            }
            else
            {
                il.Emit(EmitOpCodes.Ldc_I4_1);
            }

            il.Emit(EmitOpCodes.Brfalse, end);

            Body.Compile(context, il);
            Incrementor?.Compile(context, il);
            il.Emit(EmitOpCodes.Br, start);

            il.MarkLabel(end);
        }
示例#3
0
        public override void Compile(EmitCompilerContext context, EmitIl il)
        {
            Condition.Compile(context, il);
            var ifNotTrue = il.DefineLabel();
            il.Emit(EmitOpCodes.Brfalse, ifNotTrue);
            Statement.Compile(context, il);
            var statementReturned = il.Instructions.Last().OpCode == EmitOpCodes.Ret;

            if (Else != null)
            {
                EmitLabel end = null;
                if (!statementReturned)
                {
                    end = il.DefineLabel();
                    il.Emit(EmitOpCodes.Br, end);
                }
                il.MarkLabel(ifNotTrue);
                Else.Compile(context, il);
                if (!statementReturned)
                {
                    il.MarkLabel(end);
                    il.Emit(EmitOpCodes.Nop);
                }
            }
            else
            {
                il.MarkLabel(ifNotTrue);
            }
        }
示例#4
0
        public override void Compile(EmitCompilerContext context, EmitIl il)
        {
            Condition.Compile(context, il);
            var ifNotTrue = il.DefineLabel();

            il.Emit(EmitOpCodes.Brfalse, ifNotTrue);
            Statement.Compile(context, il);
            var statementReturned = il.Instructions.Last().OpCode == EmitOpCodes.Ret;

            if (Else != null)
            {
                EmitLabel end = null;
                if (!statementReturned)
                {
                    end = il.DefineLabel();
                    il.Emit(EmitOpCodes.Br, end);
                }
                il.MarkLabel(ifNotTrue);
                Else.Compile(context, il);
                if (!statementReturned)
                {
                    il.MarkLabel(end);
                    il.Emit(EmitOpCodes.Nop);
                }
            }
            else
            {
                il.MarkLabel(ifNotTrue);
            }
        }
示例#5
0
        public override void Compile(EmitCompilerContext context, EmitIl il)
        {
            switch (Operator)
            {
                case EmitBinaryOperator.Assign:
                    ((IEmitReferenceExpression)Left).CompileAssignment(context, il, () => Right.Compile(context, il));
                    break;
                case EmitBinaryOperator.BooleanAnd:
                    Left.Compile(context, il);
                    il.Emit(EmitOpCodes.Dup);

                    var andEnd = il.DefineLabel();
                    il.Emit(EmitOpCodes.Brfalse, andEnd);
                    il.Emit(EmitOpCodes.Pop);

                    Right.Compile(context, il);
                    il.MarkLabel(andEnd);

                    break;
                case EmitBinaryOperator.BooleanOr:
                    Left.Compile(context, il);
                    il.Emit(EmitOpCodes.Dup);

                    var orEnd = il.DefineLabel();
                    il.Emit(EmitOpCodes.Brtrue, orEnd);
                    il.Emit(EmitOpCodes.Pop);

                    Right.Compile(context, il);
                    il.MarkLabel(orEnd);

                    break;
                default:
                    var instruction = GetOpCode();
                    var isInverted = IsOperatorInverse();
                    var isAssignment = IsOperatorAssignment();

                    Left.Compile(context, il);
                    Right.Compile(context, il);

                    il.Emit(instruction);

                    if (isInverted)
                    {
                        il.Emit(EmitOpCodes.Ldc_I4_0);
                        il.Emit(EmitOpCodes.Ceq);
                    }

                    if (isAssignment)
                    {
                        var local = il.DeclareLocal(typeof(bool));
                        il.Emit(EmitOpCodes.Stloc, local);
                        ((IEmitReferenceExpression)Left).CompileAssignment(context, il, () => il.Emit(EmitOpCodes.Ldloc, local));
                    }

                    break;
            }
        }
示例#6
0
        public override void Compile(EmitCompilerContext context, EmitIl il)
        {
            var item = il.DeclareLocal(Item.Type);

            Item.SetData(context, item);

            EmitType genericEnumerableType = typeof(IEnumerable <>);
            var      enumerableType        = genericEnumerableType.MakeGenericType(Item.Type);
            var      getEnumeratorMethod   = enumerableType.Members.OfType <EmitMethod>().Single(x => x.Name == nameof(IEnumerable <object> .GetEnumerator));

            EmitType genericEnumeratorType = typeof(IEnumerator <>);
            var      enumeratorType        = genericEnumeratorType.MakeGenericType(Item.Type);
            var      moveNextMethod        = enumerableType.Members.OfType <EmitMethod>().Single(x => x.Name == nameof(IEnumerator <object> .MoveNext));
            var      getCurrentMethod      = enumerableType.Members.OfType <EmitProperty>().Single(x => x.Name == nameof(IEnumerator <object> .Current)).GetMethod;

            var enumerator = il.DeclareLocal(enumeratorType);

            Collection.Compile(context, il);
            il.Emit(EmitOpCodes.Callvirt, getEnumeratorMethod);
            il.Emit(EmitOpCodes.Stloc, enumerator);

            var topOfLoop = il.DefineLabel();
            var end       = il.DefineLabel();

            il.MarkLabel(topOfLoop);
            il.Emit(EmitOpCodes.Ldloc, enumerator);
            il.Emit(EmitOpCodes.Callvirt, moveNextMethod);
            il.Emit(EmitOpCodes.Brfalse, end);

            il.Emit(EmitOpCodes.Ldloc, enumerator);
            il.Emit(EmitOpCodes.Callvirt, getCurrentMethod);
            il.Emit(EmitOpCodes.Stloc, item);

            Statement.Compile(context, il);
            il.Emit(EmitOpCodes.Br, topOfLoop);

            il.MarkLabel(end);
            il.Emit(EmitOpCodes.Nop);
        }
示例#7
0
        public override void Compile(EmitCompilerContext context, EmitIl il)
        {
            var item = il.DeclareLocal(Item.Type);
            Item.SetData(context, item);

            EmitType genericEnumerableType = typeof(IEnumerable<>);
            var enumerableType = genericEnumerableType.MakeGenericType(Item.Type);
            var getEnumeratorMethod = enumerableType.Members.OfType<EmitMethod>().Single(x => x.Name == nameof(IEnumerable<object>.GetEnumerator));

            EmitType genericEnumeratorType = typeof(IEnumerator<>);
            var enumeratorType = genericEnumeratorType.MakeGenericType(Item.Type);
            var moveNextMethod = enumerableType.Members.OfType<EmitMethod>().Single(x => x.Name == nameof(IEnumerator<object>.MoveNext));
            var getCurrentMethod = enumerableType.Members.OfType<EmitProperty>().Single(x => x.Name == nameof(IEnumerator<object>.Current)).GetMethod;

            var enumerator = il.DeclareLocal(enumeratorType);

            Collection.Compile(context, il);
            il.Emit(EmitOpCodes.Callvirt, getEnumeratorMethod);
            il.Emit(EmitOpCodes.Stloc, enumerator);

            var topOfLoop = il.DefineLabel();
            var end = il.DefineLabel();

            il.MarkLabel(topOfLoop);
            il.Emit(EmitOpCodes.Ldloc, enumerator);
            il.Emit(EmitOpCodes.Callvirt, moveNextMethod);
            il.Emit(EmitOpCodes.Brfalse, end);

            il.Emit(EmitOpCodes.Ldloc, enumerator);
            il.Emit(EmitOpCodes.Callvirt, getCurrentMethod);
            il.Emit(EmitOpCodes.Stloc, item);

            Statement.Compile(context, il);
            il.Emit(EmitOpCodes.Br, topOfLoop);

            il.MarkLabel(end);
            il.Emit(EmitOpCodes.Nop);
        }