Пример #1
0
        private void EmitReturnStatement(CodeMethodReturnStatement Return)
        {
            Depth++;

            Debug("Emitting return statement");

            if (Method.ReturnType != typeof(void))
            {
                Type Top;
                if (Return.Expression == null)
                {
                    // Default to an empty string if this method expects a return value
                    Generator.Emit(OpCodes.Ldstr, "");
                    Top = typeof(string);
                }
                else
                {
                    Top = EmitExpression(Return.Expression);
                }

                if (Top != null)
                {
                    ForceTopStack(Top, Method.ReturnType);
                }
            }
            else if (Return.Expression != null)
            {
                throw new CompileException(Return, "Can not return value from void method " + Method.Name);
            }

            Generator.Emit(OpCodes.Ret);

            Depth--;
        }
Пример #2
0
 private void EmitArgumentReference(CodeArgumentReferenceExpression Argument)
 {
     Depth++;
     Debug("Emitting argument reference");
     Generator.Emit(OpCodes.Ldarg, 0);             // for now only used to refer to the sole object[] parameter
     Depth--;
 }
Пример #3
0
        void EmitIterationStatement(CodeIterationStatement Iterate)
        {
            Depth++;
            Debug("Emitting iteration statement");

            // Used for break and continue later on
            var Meta = new LoopMetadata {
                Begin = Generator.DefineLabel(),
                End   = Generator.DefineLabel(),
            };

            Loops.Push(Meta);

            EmitStatement(Iterate.InitStatement, false);

            // The beginning of our loop: check the limit
            Generator.MarkLabel(Meta.Begin);

            EmitExpression(Iterate.TestExpression, false);
            Generator.Emit(OpCodes.Brfalse, Meta.End);

            // Emit the actual statements within
            EmitStatementCollection(Iterate.Statements);

            // Increase the counter by one
            EmitStatement(Iterate.IncrementStatement, false);

            // Start all over again
            Generator.Emit(OpCodes.Br, Meta.Begin);
            Generator.MarkLabel(Meta.End);

            Loops.Pop();
            Depth--;
        }
Пример #4
0
        void EmitArrayIndexerExpression(CodeArrayIndexerExpression Indexer)
        {
            var index = (CodeArrayIndexerExpression)Indexer;

            Generator.Emit(OpCodes.Ldloc, VarsProperty);
            EmitExpression(index.Indices[0]);

            Generator.Emit(OpCodes.Callvirt, GetVariable);
        }
Пример #5
0
        private Type EmitArrayInitializer(Type ElementType, CodeExpression Expr, int Index)
        {
            Generator.Emit(OpCodes.Dup);
            Generator.Emit(OpCodes.Ldc_I4, Index);
            Type Generated = EmitExpression(Expr);

            ForceTopStack(Generated, ElementType);
            Generator.Emit(OpCodes.Stelem_Ref);
            return(ElementType.MakeArrayType());
        }
Пример #6
0
        private void ConditionalBox(Type Top)
        {
            if (Top == null)
            {
                throw new Exception("Top type can not be null");
            }

            if (Top != typeof(object))
            {
                Generator.Emit(OpCodes.Box, Top);
            }
        }
Пример #7
0
        private void EmitGotoStatement(CodeGotoStatement Goto)
        {
            Depth++;
            Debug("Emitting goto: " + Goto.Label);

            LabelMetadata Meta = LookupLabel(Goto.Label);

            Generator.Emit(OpCodes.Br, Meta.Label);
            Meta.From = Goto;

            Depth--;
        }
Пример #8
0
        public void Emit()
        {
            EmitStatementCollection(Member.Statements);

            if (Method.ReturnType != typeof(void))
            {
                Generator.Emit(OpCodes.Ldstr, "");
            }
            Generator.Emit(OpCodes.Ret);

            CheckLabelsResolved();
        }
Пример #9
0
        Type EmitPropertyReferenceExpression(CodePropertyReferenceExpression prop)
        {
            // HACK: property get method target
            var info = typeof(Rusty.Core).GetProperty(prop.PropertyName);

            if (Mirror != null)
            {
                info = Mirror.GrabProperty(info);
            }

            Generator.Emit(OpCodes.Call, info.GetGetMethod());
            return(info.PropertyType);
        }
Пример #10
0
        private Type EmitVariableReference(CodeVariableReferenceExpression Expr)
        {
            if (!Locals.ContainsKey(Expr.VariableName))
            {
                throw new CompileException(Expr, "Undefined variable: " + Expr.VariableName);
            }

            LocalBuilder Builder = Locals[Expr.VariableName];

            Generator.Emit(OpCodes.Ldloc, Builder);

            return(Builder.LocalType);
        }
Пример #11
0
        private void EmitAssignStatement(CodeAssignStatement Assign, bool ForceTypes)
        {
            Depth++;
            Debug("Emitting assignment statement");
            Type Top = EmitAssignment(Assign.Left, Assign.Right, ForceTypes);

            if (Top != typeof(void))
            {
                Generator.Emit(OpCodes.Pop);
            }

            Depth--;
        }
Пример #12
0
        private void EmitVariableDeclarationStatement(CodeVariableDeclarationStatement Statement)
        {
            if (Locals.ContainsKey(Statement.Name))
            {
                throw new CompileException(Statement, "Attempt to redefine local variable " + Statement.Name);
            }

            Type         Top   = EmitExpression(Statement.InitExpression);
            LocalBuilder Local = Generator.DeclareLocal(Top);

            Locals.Add(Statement.Name, Local);

            Generator.Emit(OpCodes.Stloc, Local);
        }
Пример #13
0
        Type EmitExpressionStatement(CodeExpressionStatement Expression, bool ForceTypes)
        {
            Depth++;
            Debug("Emitting expression statement");
            Type Generated = EmitExpression(Expression.Expression, ForceTypes);

            if (Generated != typeof(void))
            {
                Generator.Emit(OpCodes.Pop);
            }

            Depth--;

            return(Generated);
        }
Пример #14
0
 private void ForceTopStack(Type Top, Type Wanted, bool ForceTypes)
 {
     Depth++;
     if (Top != Wanted)
     {
         Debug("Forcing top stack " + Top + " to " + Wanted);
         if (Wanted == typeof(string))
         {
             ConditionalBox(Top);
             Generator.Emit(OpCodes.Call, ForceString);
         }
         else if (Wanted == typeof(decimal))
         {
             ConditionalBox(Top);
             Generator.Emit(OpCodes.Call, ForceDecimal);
         }
         else if (Wanted == typeof(long))
         {
             ConditionalBox(Top);
             Generator.Emit(OpCodes.Call, ForceLong);
         }
         else if (Wanted == typeof(int))
         {
             ConditionalBox(Top);
             Generator.Emit(OpCodes.Call, ForceInt);
         }
         else if (Wanted == typeof(bool))
         {
             ConditionalBox(Top);
             Generator.Emit(OpCodes.Call, ForceBool);
         }
         else if (Wanted == typeof(object))
         {
             ConditionalBox(Top);
         }
         else if (Wanted == typeof(object[]) && Top.IsArray)
         {
         }
         else
         {
             Debug("WARNING: Can not force " + Wanted);
         }
     }
     Depth--;
 }
Пример #15
0
        Type EmitTernaryOperator(CodeTernaryOperatorExpression ternary)
        {
            Label FalseLabel = Generator.DefineLabel();
            Label EndLabel   = Generator.DefineLabel();
            Type  Top;

            EmitExpression(ternary.Condition);
            Generator.Emit(OpCodes.Brfalse, FalseLabel);
            Top = EmitExpression(ternary.TrueBranch);
            ForceTopStack(Top, typeof(object));
            Generator.Emit(OpCodes.Br, EndLabel);
            Generator.MarkLabel(FalseLabel);
            Top = EmitExpression(ternary.FalseBranch);
            ForceTopStack(Top, typeof(object));
            Generator.MarkLabel(EndLabel);

            return(typeof(object));
        }
Пример #16
0
        Type EmitCodeFieldReference(CodeFieldReferenceExpression field)
        {
            Depth++;
            Debug("Emitting field reference: " + field.FieldName);

            Type      target = Type.GetType((field.TargetObject as CodeTypeReferenceExpression).Type.BaseType);
            FieldInfo fi     = target.GetField(field.FieldName);

            try
            {
                Generator.Emit(OpCodes.Ldc_I4, (int)fi.GetValue(null));
            }
            catch (InvalidCastException)
            {
                throw new CompileException(field, "Enumerator " + target.Name + " does not have base type of int32");
            }

            Depth--;
            return(fi.FieldType);
        }
Пример #17
0
        private void EmitConditionStatement(CodeConditionStatement Condition)
        {
            Label False = Generator.DefineLabel();
            Label End   = Generator.DefineLabel();

            // TODO: emitting condition statements could probably be done more efficiently
            EmitExpression(Condition.Condition);
            Generator.Emit(OpCodes.Ldc_I4_0);
            Generator.Emit(OpCodes.Beq, False);

            // Execute code for true and jump to end
            EmitStatementCollection(Condition.TrueStatements);
            Generator.Emit(OpCodes.Br, End);

            // Execute code for false and move on
            Generator.MarkLabel(False);
            EmitStatementCollection(Condition.FalseStatements);

            Generator.MarkLabel(End);
        }
Пример #18
0
        Type EmitPrimitive(CodePrimitiveExpression Primitive)
        {
            Type T;

            if (Primitive.Value == null)
            {
                T = null;
            }
            else
            {
                T = Primitive.Value.GetType();
            }

            if (T != null && T.IsArray)
            {
                var  Contents = Primitive.Value as object[];
                Type Element  = T.GetElementType();
                Generator.Emit(OpCodes.Ldc_I4, Contents.Length);
                Generator.Emit(OpCodes.Newarr, Element);

                int i = 0;
                foreach (var Value in Contents)
                {
                    Generator.Emit(OpCodes.Dup);
                    Generator.Emit(OpCodes.Ldc_I4, i);

                    EmitLiteral(Element, Value);
                    Generator.Emit(OpCodes.Stelem_Ref);

                    i++;
                }

                return(T);
            }
            else
            {
                return(EmitLiteral(T, Primitive.Value));
            }
        }
Пример #19
0
        Type EmitDelegateCreateExpression(CodeDelegateCreateExpression del)
        {
            Depth++;
            Debug("Emitting delegate: " + del.MethodName);

            // HACK: use generic method lookup for emitting delegates

            if (!Methods.ContainsKey(del.MethodName))
            {
                throw new CompileException(del, "Delegate function does not exist in local scope");
            }

            var method = (MethodInfo)Methods[del.MethodName].Method;

            Generator.Emit(OpCodes.Ldnull);
            Generator.Emit(OpCodes.Ldftn, method);

            var type = del.DelegateType.UserData[Parser.RawData] as Type ?? Type.GetType(del.DelegateType.BaseType);

            if (type == null)
            {
                throw new CompileException(del, "Invalid delegate type");
            }

            if (Mirror != null)
            {
                type = Mirror.GrabType(type);
            }

            var ctor = type.GetConstructors()[0];

            Generator.Emit(OpCodes.Newobj, ctor);

            Depth--;

            return(type);
        }
Пример #20
0
        Type EmitMethodInvoke(CodeMethodInvokeExpression invoke)
        {
            Depth++;
            Debug("Emitting method " + invoke.Method.MethodName);

            MethodInfo target = null;

            Type[] types = null;

            #region Lookup target function
            MethodInfo actual = null;
            if (invoke.Method.TargetObject != null)
            {
                target = GetMethodInfo(invoke.Method);

                if (Mirror != null)
                {
                    actual = Mirror.GrabMethod(target);
                }
            }

            // Case insensitive method search in local scope
            if (target == null)
            {
                foreach (var name in Methods.Keys)
                {
                    if (invoke.Method.MethodName.Equals(name, StringComparison.OrdinalIgnoreCase))
                    {
                        invoke.Method.MethodName = name;
                    }
                }
            }

            // First we check the local methods
            if (target == null && Methods.ContainsKey(invoke.Method.MethodName))
            {
                types  = ParameterTypes[invoke.Method.MethodName];
                target = Methods[invoke.Method.MethodName].Method;
            }

            // Then the methods provided by rusty
            if (target == null)
            {
                target = Lookup.BestMatch(invoke.Method.MethodName, invoke.Parameters.Count);

                if (Mirror != null)
                {
                    actual = Mirror.GrabMethod(target);
                }
            }

            // Lastly, the native methods
            if (target == null && invoke.Method.TargetObject != null)
            {
                target = GetMethodInfo(invoke.Method);

                if (Mirror != null)
                {
                    actual = Mirror.GrabMethod(target);
                }
            }

            if (target == null)
            {
                throw new CompileException(invoke, "Could not look up method " + invoke.Method.MethodName);
            }

            bool hasParams = false;
            if (types == null) // Rusty-defined or native method
            {
                ParameterInfo[] Params = target.GetParameters();
                types = new Type[Params.Length];
                for (int i = 0; i < Params.Length; i++)
                {
                    types[i] = Params[i].ParameterType;
                }

                hasParams = types.Length == 0 ? false : types[types.Length - 1] == typeof(object[]);
            }
            #endregion

            #region Emit parameters
            int p = 0;

            var ByRef = new Dictionary <LocalBuilder, CodeExpression>();

            for (p = 0; p < invoke.Parameters.Count; p++)
            {
                Depth++;
                Debug("Emitting parameter " + p);

                // Collapse superfluous arguments in array if last argument is object[]
                // _and_ it's not a call into a user-defined function.
                if (hasParams)
                {
                    if (p == types.Length - 1)
                    {
                        Type Generated = EmitExpression(invoke.Parameters[p]);

                        // If the last argument is object[], we don't bother about params
                        if (Generated == typeof(object[]))
                        {
                            break;
                        }

                        LocalBuilder Temp = Generator.DeclareLocal(typeof(object));
                        ForceTopStack(Generated, typeof(object));
                        Generator.Emit(OpCodes.Stloc, Temp);

                        EmitArrayCreation(typeof(object), invoke.Parameters.Count - p);

                        Generator.Emit(OpCodes.Dup);
                        Generator.Emit(OpCodes.Ldc_I4, 0);
                        Generator.Emit(OpCodes.Ldloc, Temp);
                        Generator.Emit(OpCodes.Stelem_Ref);

                        Depth--;
                        continue;
                    }
                    else if (p > types.Length - 1)
                    {
                        EmitArrayInitializer(typeof(object), invoke.Parameters[p], p - types.Length + 1);

                        Depth--;
                        continue;
                    }
                }

                if (p < types.Length)
                {
                    Type Generated = EmitExpression(invoke.Parameters[p]);

                    if (types[p].IsByRef)
                    {
                        // Variables passed by reference need to be stored in a local
                        Debug("Parameter " + p + " was by reference");
                        LocalBuilder Temporary = Generator.DeclareLocal(types[p].GetElementType());
                        ForceTopStack(typeof(object), types[p].GetElementType());
                        Generator.Emit(OpCodes.Stloc, Temporary);
                        Generator.Emit(OpCodes.Ldloca_S, Temporary);

                        if (invoke.Parameters[p] is CodeArrayIndexerExpression)
                        {
                            ByRef.Add(Temporary, invoke.Parameters[p]);
                        }
                    }
                    else
                    {
                        ForceTopStack(Generated, types[p]);
                    }
                }

                Depth--;
            }

            // Anything not specified pads to the default IL value
            while (p < types.Length)
            {
                if (types[p].IsByRef)
                {
                    Type NotRef = types[p].GetElementType();
                    EmitLiteral(NotRef, GetDefaultValue(target.GetParameters()[p]));
                    LocalBuilder Temporary = Generator.DeclareLocal(NotRef);
                    Generator.Emit(OpCodes.Stloc, Temporary);
                    Generator.Emit(OpCodes.Ldloca, Temporary);
                }
                else
                {
                    EmitLiteral(types[p], GetDefaultValue(target.GetParameters()[p]));
                }
                p++;
            }
            #endregion

            if (actual == null)
            {
                Generator.Emit(OpCodes.Call, target);
            }
            else
            {
                Generator.Emit(OpCodes.Call, actual);
            }

            #region Save back the variables
            // Save the variables passed to reference back in Rusty's variable handling
            foreach (var Builder in ByRef.Keys)
            {
                if (ByRef[Builder] is CodeArrayIndexerExpression)
                {
                    var Ref = ByRef[Builder] as CodeArrayIndexerExpression;
                    Generator.Emit(OpCodes.Ldloc, VarsProperty);
                    EmitExpression(Ref.Indices[0]);
                    Generator.Emit(OpCodes.Ldloc, Builder);

                    if (Builder.LocalType != typeof(object))
                    {
                        ForceTopStack(Builder.LocalType, typeof(object));
                    }

                    Generator.Emit(OpCodes.Callvirt, SetVariable);
                    Generator.Emit(OpCodes.Pop);
                }
            }
            #endregion

            Depth--;
            return(target.ReturnType);
        }
Пример #21
0
        private Type EmitAssignment(CodeExpression Left, CodeExpression Right, bool ForceTypes)
        {
            Depth++;
            Debug("Emitting assignment expression");
            Type Generated = typeof(void);

            if (Left is CodeVariableReferenceExpression)
            {
                // local IL variables generated by parser
                var Reference = Left as CodeVariableReferenceExpression;

                LocalBuilder Var;
                if (Locals.ContainsKey(Reference.VariableName))
                {
                    Var = Locals[Reference.VariableName];
                }
                else
                {
                    Var = Generator.DeclareLocal(typeof(int));
                    Locals.Add(Reference.VariableName, Var);
                }

                EmitExpression(Right, ForceTypes);
                Generator.Emit(OpCodes.Stloc, Var);
                Generator.Emit(OpCodes.Pop);
            }
            else if (Left is CodeArrayIndexerExpression)
            {
                var index = (CodeArrayIndexerExpression)Left;

                Generator.Emit(OpCodes.Ldloc, VarsProperty);

                EmitExpression(index.Indices[0]);
                Type resultType = EmitExpression(Right, ForceTypes);
                if (resultType.IsValueType)
                {
                    Generator.Emit(OpCodes.Box, resultType);
                }

                Generator.Emit(OpCodes.Callvirt, SetVariable);

                Generated = typeof(object);
            }
            else if (Left is CodePropertyReferenceExpression)
            {
                var prop = (CodePropertyReferenceExpression)Left;

                // HACK: property set method target
                var info = typeof(Rusty.Core).GetProperty(prop.PropertyName);

                if (Mirror != null)
                {
                    info = Mirror.GrabProperty(info);
                }

                var set = info == null ? null : info.GetSetMethod();

                if (set == null)
                {
                    Generator.Emit(OpCodes.Ldnull);
                }
                else
                {
                    EmitExpression(Right);
                    Generator.Emit(OpCodes.Dup);
                    Generator.Emit(OpCodes.Call, set);
                }

                Generated = typeof(object);
            }
            else
            {
                throw new CompileException(Left, "Left hand is unassignable");
            }

            Depth--;

            return(Generated);
        }
Пример #22
0
        Type EmitLiteral(Type T, object Value)
        {
            Depth++;
            Type Generated = T;

            if (Value == null)
            {
                Debug("Pushing null");
                Generator.Emit(OpCodes.Ldnull);
                Generated = typeof(Nullable);
            }
            else if (T == typeof(string))
            {
                Debug("Pushing primitive string : \"" + (Value as string) + "\"");

                if (((string)Value).Length == 0)
                {
                    Generator.Emit(OpCodes.Ldsfld, typeof(string).GetField("Empty"));
                }
                else
                {
                    Generator.Emit(OpCodes.Ldstr, Value as string);
                }
            }
            else if (T == typeof(int))
            {
                var val = (int)Value;
                Debug("Pushing primitive integer : " + val);

                switch (val)
                {
                case -1: Generator.Emit(OpCodes.Ldc_I4_M1); break;

                case 0: Generator.Emit(OpCodes.Ldc_I4_0); break;

                case 1: Generator.Emit(OpCodes.Ldc_I4_1); break;

                case 2: Generator.Emit(OpCodes.Ldc_I4_2); break;

                case 3: Generator.Emit(OpCodes.Ldc_I4_3); break;

                case 4: Generator.Emit(OpCodes.Ldc_I4_4); break;

                case 5: Generator.Emit(OpCodes.Ldc_I4_5); break;

                case 6: Generator.Emit(OpCodes.Ldc_I4_6); break;

                case 7: Generator.Emit(OpCodes.Ldc_I4_7); break;

                case 8: Generator.Emit(OpCodes.Ldc_I4_8); break;

                default: Generator.Emit(OpCodes.Ldc_I4, val); break;
                }
            }
            else if (T == typeof(decimal))
            {
                Debug("Pushing decimal : " + ((decimal)Value));

                // HACK:  push real decimals without downcasting
                // i.e. new decimal(decimal.GetBits((decimal)Value));

                Generator.Emit(OpCodes.Ldc_R8, ((double)((decimal)Value)));
                Generated = typeof(double);
            }
            else if (T == typeof(object[]))
            {
                Debug("Pushing object[" + ((object[])Value).Length + "]");
                var array = new CodeArrayCreateExpression();
                array.CreateType = new CodeTypeReference(typeof(object));

                foreach (var sub in (object[])Value)
                {
                    array.Initializers.Add(new CodePrimitiveExpression(sub));
                }

                EmitDynamicName(array);
            }
            else if (T == typeof(bool))
            {
                var val = (bool)Value;
                Debug("Pushing bool: " + Value);

                Generator.Emit(val ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
            }
            else if (T == typeof(double))
            {
                Debug("Pushing double: " + ((double)Value));
                Generator.Emit(OpCodes.Ldc_R8, ((double)Value));
            }
            else if (T == typeof(long))
            {
                Debug("Pushing long: " + (long)Value);
                Generator.Emit(OpCodes.Ldc_I8, (long)Value);
            }
            else if (T.IsGenericType && T.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                Debug("Pushing nullable: " + Value);
                EmitLiteral(Value == null ? typeof(Nullable) : T.GetGenericArguments()[0], Value);
            }
            else
            {
                Debug("Unhandled primitive: " + T);
                Generated = null;
            }
            Depth--;

            return(Generated);
        }
Пример #23
0
 private Type EmitArrayCreation(Type ArrayType, int Count)
 {
     Generator.Emit(OpCodes.Ldc_I4, Count);
     Generator.Emit(OpCodes.Newarr, ArrayType);
     return(ArrayType.MakeArrayType());
 }
Пример #24
0
        Type EmitBinaryOperator(CodeBinaryOperatorExpression Binary, bool ForceTypes)
        {
            bool  Shortcut = Binary.Operator == CodeBinaryOperatorType.BooleanAnd || Binary.Operator == CodeBinaryOperatorType.BooleanOr;
            Label EndLabel = Generator.DefineLabel();

            if (Binary.Operator == CodeBinaryOperatorType.Assign)
            {
                return(EmitAssignment(Binary.Left, Binary.Right, ForceTypes));
            }

            Type Generated;

            Depth++;
            Debug("Emitting binary operator, left hand side");
            Generated = EmitExpression(Binary.Left);

            if (Shortcut && Generated == typeof(bool))
            {
                Debug("Short-circuiting expression for " + Binary.Operator);
                Generator.Emit(OpCodes.Dup);

                if (Binary.Operator == CodeBinaryOperatorType.BooleanAnd)
                {
                    Generator.Emit(OpCodes.Brfalse, EndLabel); // BooleanAnd jumps if left branch evals false
                }
                else if (Binary.Operator == CodeBinaryOperatorType.BooleanOr)
                {
                    Generator.Emit(OpCodes.Brtrue, EndLabel); // BooleanOr jumps if left branch evals true
                }
            }

            if (ForceTypes)
            {
                ForceTopStack(Generated, typeof(float));
            }
            Debug("Emitting binary operator, right hand side");
            Generated = EmitExpression(Binary.Right);
            if (ForceTypes)
            {
                ForceTopStack(Generated, typeof(float));
            }

            if (Shortcut)
            {
                if (Binary.Operator == CodeBinaryOperatorType.BooleanAnd)
                {
                    Generator.Emit(OpCodes.And);
                }
                else if (Binary.Operator == CodeBinaryOperatorType.BooleanOr)
                {
                    Generator.Emit(OpCodes.Or);
                }

                // Handy side-effect: one bool caused by the "dup" stays on the stack
                // Resulting in the whole expression evaluating correctly anyway.
                Generator.MarkLabel(EndLabel);

                Depth--;
                return(typeof(bool));
            }

            switch (Binary.Operator)
            {
            case CodeBinaryOperatorType.Add:
                Generator.Emit(OpCodes.Add);
                Generated = typeof(float);
                break;

            case CodeBinaryOperatorType.Subtract:
                Generator.Emit(OpCodes.Sub);
                Generated = typeof(float);
                break;

            case CodeBinaryOperatorType.Multiply:
                Generator.Emit(OpCodes.Mul);
                Generated = typeof(float);
                break;

            case CodeBinaryOperatorType.Divide:
                Generator.Emit(OpCodes.Div);
                Generated = typeof(float);
                break;

            case CodeBinaryOperatorType.LessThan:
                Generator.Emit(OpCodes.Clt);
                Generated = typeof(bool);
                break;

            case CodeBinaryOperatorType.GreaterThan:
                Generator.Emit(OpCodes.Cgt);
                Generated = typeof(bool);
                break;

            case CodeBinaryOperatorType.ValueEquality:
                Generator.Emit(OpCodes.Ceq);
                Generated = typeof(bool);
                break;

            default:
                Debug("Unhandled operator: " + Binary.Operator);
                Generated = null;
                break;
            }

            Depth--;

            return(Generated);
        }