protected override void EmitOperator(Context ctx) { var gen = ctx.CurrentMethod.Generator; LeftOperand.Emit(ctx, true); RightOperand.Emit(ctx, true); gen.EmitShift(IsLeft); }
/// <summary> /// Emits code for relation comparison: greater, less, etc. /// </summary> private void EmitRelation(Context ctx, Type left, Type right) { var gen = ctx.CurrentMethod.Generator; // string comparisons if (left == typeof(string)) { LeftOperand.Emit(ctx, true); RightOperand.Emit(ctx, true); var method = typeof(string).GetMethod("Compare", new[] { typeof(string), typeof(string) }); gen.EmitCall(method); if (Kind.IsAnyOf(ComparisonOperatorKind.Less, ComparisonOperatorKind.GreaterEquals)) { gen.EmitConstant(-1); gen.EmitCompareEqual(); if (Kind == ComparisonOperatorKind.GreaterEquals) { EmitInversion(gen); } } else { gen.EmitConstant(1); gen.EmitCompareEqual(); if (Kind == ComparisonOperatorKind.LessEquals) { EmitInversion(gen); } } } // numeric comparison LoadAndConvertNumerics(ctx); if (Kind.IsAnyOf(ComparisonOperatorKind.Less, ComparisonOperatorKind.GreaterEquals)) { gen.EmitCompareLess(); if (Kind == ComparisonOperatorKind.GreaterEquals) { EmitInversion(gen); } } else { gen.EmitCompareGreater(); if (Kind == ComparisonOperatorKind.LessEquals) { EmitInversion(gen); } } }
protected override void EmitOperator(Context ctx) { var gen = ctx.CurrentMethod.Generator; if (LeftOperand.Resolve(ctx).IsNumericType()) { LoadAndConvertNumerics(ctx); } else { LeftOperand.Emit(ctx, true); RightOperand.Emit(ctx, true); } gen.EmitXor(); }
protected override void emitOperator(Context ctx) { if (RightOperand.IsConstant && RightOperand.ConstantValue is int) { var constPower = (int)RightOperand.ConstantValue; if (constPower > 0 && constPower <= 10) { var gen = ctx.CurrentMethod.Generator; // detect maximum power of 2 inside current power var squareCount = 0; var powerOf2 = 1; while (constPower - powerOf2 >= powerOf2) { powerOf2 *= 2; squareCount++; } var multCount = constPower - powerOf2; LeftOperand.Emit(ctx, true); gen.EmitConvert(typeof(double)); for (var i = 0; i < multCount; i++) { gen.EmitDup(); } for (var i = 0; i < squareCount; i++) { gen.EmitDup(); gen.EmitMultiply(); } for (var i = 0; i < multCount; i++) { gen.EmitMultiply(); } return; } } loadAndConvertNumerics(ctx, typeof(double)); ctx.CurrentMethod.Generator.EmitCall(_PowMethod); }
protected override void emitOperator(Context ctx) { var gen = ctx.CurrentMethod.Generator; LeftOperand.Emit(ctx, true); RightOperand.Emit(ctx, true); if (Kind == LogicalOperatorKind.And) { gen.EmitAnd(); } else if (Kind == LogicalOperatorKind.Or) { gen.EmitOr(); } else { gen.EmitXor(); } }
/// <summary> /// Emits code for equality and inequality comparison. /// </summary> private void EmitEqualityComparison(Context ctx, Type left, Type right) { var gen = ctx.CurrentMethod.Generator; // compare two strings if (left == right && left == typeof(string)) { LeftOperand.Emit(ctx, true); RightOperand.Emit(ctx, true); var method = typeof(string).GetMethod("Equals", new[] { typeof(string), typeof(string) }); gen.EmitCall(method); if (Kind == ComparisonOperatorKind.NotEquals) { EmitInversion(gen); } return; } // compare primitive types if ((left.IsNumericType() && right.IsNumericType()) || (left == right && left == typeof(bool))) { if (left == typeof(bool)) { LeftOperand.Emit(ctx, true); RightOperand.Emit(ctx, true); } else { LoadAndConvertNumerics(ctx); } gen.EmitCompareEqual(); if (Kind == ComparisonOperatorKind.NotEquals) { EmitInversion(gen); } return; } // compare nullable against another nullable, it's base type or null if (left.IsNullableType()) { if (left == right || Nullable.GetUnderlyingType(left) == right) { EmitNullableComparison(ctx, LeftOperand, RightOperand); } else if (right == typeof(NullType)) { EmitHasValueCheck(ctx, LeftOperand); } return; } if (right.IsNullableType()) { if (Nullable.GetUnderlyingType(right) == left) { EmitNullableComparison(ctx, RightOperand, LeftOperand); } else if (left == typeof(NullType)) { EmitHasValueCheck(ctx, RightOperand); } return; } // compare a reftype against a null if (left == typeof(NullType) || right == typeof(NullType)) { LeftOperand.Emit(ctx, true); RightOperand.Emit(ctx, true); gen.EmitCompareEqual(); if (Kind == ComparisonOperatorKind.NotEquals) { EmitInversion(gen); } return; } if (left is TypeBuilder && left == right) { var equals = ctx.ResolveMethod(left, "Equals", new[] { typeof(object) }); LeftOperand.Emit(ctx, true); RightOperand.Emit(ctx, true); gen.EmitCall(equals.MethodInfo); if (Kind == ComparisonOperatorKind.NotEquals) { EmitInversion(gen); } return; } throw new ArgumentException("Unknown types to compare!"); }