Ancestry.QueryProcessor.Type.BaseType.EmitBinaryOperator C# (CSharp) Method

EmitBinaryOperator() protected method

Overridden to determine what operators a type supports and to change how they are implemented.
Override this rather than CompileBinaryOperator when nothing special is necessary when compiling the right-hand expression.
protected EmitBinaryOperator ( MethodContext method, Compiler compiler, ExpressionContext left, ExpressionContext right, Parse expression ) : void
method Ancestry.QueryProcessor.Compile.MethodContext
compiler Compiler
left Ancestry.QueryProcessor.Compile.ExpressionContext
right Ancestry.QueryProcessor.Compile.ExpressionContext
expression Parse
return void
        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);
            }
        }