예제 #1
0
        public override void OutputIL(NitroIL into)
        {
            // Emit any set operations before the block itself (e.g. i=0):
            for (int i = 0; i < Parameters.Length; i++)
            {
                CompiledFragment parameter = Parameters[i];

                if (Types.IsTypeOf(parameter, typeof(SetOperation)))
                {
                    // Make sure it isn't a self set - e.g. i++, i=i+10.
                    SetOperation set = (SetOperation)parameter;

                    if (!set.SelfReferencing())
                    {
                        set.OutputIL(into);
                        Parameters[i] = null;
                    }
                    else
                    {
                        set.Output = false;
                    }
                }
                else
                {
                    // Compute it's output type:
                    // Note that this must NOT be done for the SET ops as it makes them think
                    // We want to use their output, which isn't true!
                    parameter.OutputType(out parameter);
                    Parameters[i] = parameter;
                }
            }

            Label continuePoint = into.DefineLabel();
            Label start         = into.DefineLabel();
            Label end           = into.DefineLabel();

            Method.AddBreakPoint(new BreakPoint(continuePoint, end));
            into.MarkLabel(start);

            // Logical operations (e.g. i<10):
            for (int i = 0; i < Parameters.Length; i++)
            {
                CompiledFragment parameter = Parameters[i];

                if (parameter == null)
                {
                    continue;
                }

                if (Types.IsTypeOf(parameter, typeof(SetOperation)))
                {
                    // Just checking for a logical operation will make an incremental (i++) operation think
                    // It's being daisy chained. That's because its output type is checked for boolean in IsLogical.
                    continue;
                }

                if (parameter.IsLogical())
                {
                    parameter.OutputIL(into);
                    into.Emit(OpCodes.Brfalse, end);
                    Parameters[i] = null;
                }
            }

            Body.CompileBody(Method);
            into.MarkLabel(continuePoint);

            // Increment/decrement ops (e.g. i++):
            for (int i = 0; i < Parameters.Length; i++)
            {
                CompiledFragment cfrag = Parameters[i];
                if (cfrag == null)
                {
                    continue;
                }
                cfrag.OutputIL(into);
            }
            into.Emit(OpCodes.Br, start);
            into.MarkLabel(end);
            Method.PopBreakPoint();
        }