public void BinaryExpression(BinaryExpression binaryExpression) { switch (binaryExpression.ExpressionType) { case ExpressionType.Add: case ExpressionType.Divide: case ExpressionType.Multiply: case ExpressionType.Subtract: case ExpressionType.Equals: case ExpressionType.NotEquals: case ExpressionType.Greater: case ExpressionType.GreaterOrEquals: case ExpressionType.Less: case ExpressionType.LessOrEquals: case ExpressionType.Modulo: BinaryArithicExpression(binaryExpression); break; case ExpressionType.ShiftLeft: case ExpressionType.ShiftRight: BinaryShiftExpression(binaryExpression); break; case ExpressionType.And: case ExpressionType.Or: case ExpressionType.Xor: if (TypeUtil.IsInteger(binaryExpression.CommonType)) { BinaryBitwiseExpression(binaryExpression); } else { BinaryLogicalExpression(binaryExpression); } break; case ExpressionType.LogicalAnd: case ExpressionType.AndBoth: case ExpressionType.LogicalOr: case ExpressionType.OrBoth: BinaryLogicalExpression(binaryExpression); break; case ExpressionType.BitwiseAnd: case ExpressionType.BitwiseOr: BinaryBitwiseExpression(binaryExpression); break; default: throw new NotSupportedException(); } }
public void UnaryExpression(UnaryExpression unaryExpression) { switch (unaryExpression.ExpressionType) { case ExpressionType.Minus: unaryExpression.Operand.Accept(this); _il.Emit(OpCodes.Neg); break; case ExpressionType.Not: unaryExpression.Operand.Accept(this); if (TypeUtil.IsInteger(unaryExpression.Operand.Type)) { _il.Emit(OpCodes.Not); } else { ILUtil.EmitConstant(_il, 0); _il.Emit(OpCodes.Ceq); } break; case ExpressionType.LogicalNot: unaryExpression.Operand.Accept(this); ILUtil.EmitConstant(_il, 0); _il.Emit(OpCodes.Ceq); break; case ExpressionType.BitwiseNot: unaryExpression.Operand.Accept(this); _il.Emit(OpCodes.Not); break; case ExpressionType.Plus: case ExpressionType.Group: // No-ops. unaryExpression.Operand.Accept(this); break; default: throw new NotSupportedException(); } }
private void BinaryArithicExpression(BinaryExpression binaryExpression) { // Reference compares. if ( !binaryExpression.Left.Type.IsValueType && !binaryExpression.Right.Type.IsValueType && ( binaryExpression.ExpressionType == ExpressionType.Equals || binaryExpression.ExpressionType == ExpressionType.NotEquals ) ) { binaryExpression.Left.Accept(this); binaryExpression.Right.Accept(this); _il.Emit(OpCodes.Ceq); if (binaryExpression.ExpressionType == ExpressionType.NotEquals) { _il.Emit(OpCodes.Ldc_I4_0); _il.Emit(OpCodes.Ceq); } return; } Emit(binaryExpression.Left, binaryExpression.CommonType); Emit(binaryExpression.Right, binaryExpression.CommonType); switch (binaryExpression.ExpressionType) { case ExpressionType.Equals: case ExpressionType.NotEquals: _il.Emit(OpCodes.Ceq); if (binaryExpression.ExpressionType == ExpressionType.NotEquals) { _il.Emit(OpCodes.Ldc_I4_0); _il.Emit(OpCodes.Ceq); } break; case ExpressionType.Greater: case ExpressionType.LessOrEquals: if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) { _il.Emit(OpCodes.Cgt_Un); } else { _il.Emit(OpCodes.Cgt); } if (binaryExpression.ExpressionType == ExpressionType.LessOrEquals) { _il.Emit(OpCodes.Ldc_I4_0); _il.Emit(OpCodes.Ceq); } break; case ExpressionType.Less: case ExpressionType.GreaterOrEquals: if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) { _il.Emit(OpCodes.Clt_Un); } else { _il.Emit(OpCodes.Clt); } if (binaryExpression.ExpressionType == ExpressionType.GreaterOrEquals) { _il.Emit(OpCodes.Ldc_I4_0); _il.Emit(OpCodes.Ceq); } break; case ExpressionType.Add: if (_compiler._resolver.Options.Checked && TypeUtil.IsInteger(binaryExpression.CommonType)) { if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) { _il.Emit(OpCodes.Add_Ovf_Un); } else { _il.Emit(OpCodes.Add_Ovf); } } else { _il.Emit(OpCodes.Add); } break; case ExpressionType.Divide: if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) { _il.Emit(OpCodes.Div_Un); } else { _il.Emit(OpCodes.Div); } break; case ExpressionType.Multiply: if (_compiler._resolver.Options.Checked && TypeUtil.IsInteger(binaryExpression.CommonType)) { if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) { _il.Emit(OpCodes.Mul_Ovf_Un); } else { _il.Emit(OpCodes.Mul_Ovf); } } else { _il.Emit(OpCodes.Mul); } break; case ExpressionType.Subtract: if (_compiler._resolver.Options.Checked && TypeUtil.IsInteger(binaryExpression.CommonType)) { if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) { _il.Emit(OpCodes.Sub_Ovf_Un); } else { _il.Emit(OpCodes.Sub_Ovf); } } else { _il.Emit(OpCodes.Sub); } break; case ExpressionType.Modulo: if (TypeUtil.IsUnsigned(binaryExpression.CommonType)) { _il.Emit(OpCodes.Rem_Un); } else { _il.Emit(OpCodes.Rem); } break; default: throw new InvalidOperationException(); } }
private Type ResolveExpressionType(Type left, Type right, Type commonType, ExpressionType type) { Require.NotNull(left, "left"); Require.NotNull(right, "right"); // TODO: Implicit/explicit operators and operators for the expression type. // Boolean operators. switch (type) { case ExpressionType.And: case ExpressionType.Or: case ExpressionType.Xor: case ExpressionType.AndBoth: case ExpressionType.OrBoth: if (TypeUtil.IsInteger(commonType)) { return(commonType); } else if (left != typeof(bool) || right != typeof(bool)) { throw new ExpressionsException("Invalid operand for expression type", ExpressionsExceptionType.TypeMismatch); } return(typeof(bool)); case ExpressionType.Greater: case ExpressionType.GreaterOrEquals: case ExpressionType.Less: case ExpressionType.LessOrEquals: if ( !(left.IsEnum || TypeUtil.IsNumeric(left)) || !(right.IsEnum || TypeUtil.IsNumeric(right)) ) { throw new ExpressionsException("Invalid operand for expression type", ExpressionsExceptionType.TypeMismatch); } return(typeof(bool)); case ExpressionType.Equals: case ExpressionType.NotEquals: case ExpressionType.In: case ExpressionType.LogicalAnd: case ExpressionType.LogicalOr: case ExpressionType.Compares: case ExpressionType.NotCompares: return(typeof(bool)); case ExpressionType.Add: if ( !(left == typeof(string) || right == typeof(string)) && !(TypeUtil.IsNumeric(left) && TypeUtil.IsNumeric(right)) ) { throw new ExpressionsException("Invalid operand for expression type", ExpressionsExceptionType.TypeMismatch); } return(commonType); case ExpressionType.Subtract: case ExpressionType.Multiply: case ExpressionType.Divide: case ExpressionType.Power: if (!TypeUtil.IsNumeric(left) || !TypeUtil.IsNumeric(right)) { throw new ExpressionsException("Invalid operand for expression type", ExpressionsExceptionType.TypeMismatch); } return(commonType); default: return(commonType); } }
private bool IsAllowableImplicit(Type a, Type b) { return(TypeUtil.IsInteger(a) == TypeUtil.IsInteger(b)); }
public IExpression UnaryExpression(Ast.UnaryExpression unaryExpression) { var operand = unaryExpression.Operand.Accept(this); string operatorName = null; switch (unaryExpression.Type) { case ExpressionType.Plus: operatorName = "op_UnaryPlus"; break; case ExpressionType.Minus: operatorName = "op_UnaryNegation"; break; case ExpressionType.Not: case ExpressionType.LogicalNot: operatorName = "op_Negation"; break; } if (operatorName != null) { var method = _resolver.FindOperatorMethod( operatorName, new[] { operand.Type }, null, new[] { operand.Type } ); if (method != null) { return(new Expressions.MethodCall( new TypeAccess(method.DeclaringType), method, new[] { operand } )); } } Type type; switch (unaryExpression.Type) { case ExpressionType.Plus: if (!TypeUtil.IsValidUnaryArgument(operand.Type)) { throw new ExpressionsException("Operand of plus operation must be an integer type", ExpressionsExceptionType.TypeMismatch); } type = operand.Type; break; case ExpressionType.Group: type = operand.Type; break; case ExpressionType.Minus: if (!TypeUtil.IsValidUnaryArgument(operand.Type)) { throw new ExpressionsException("Operand of minus operation must be an integer type", ExpressionsExceptionType.TypeMismatch); } // TODO: Make constants signed and handle minus on unsigned's. type = operand.Type; break; case ExpressionType.LogicalNot: if (operand.Type != typeof(bool)) { throw new ExpressionsException("Operand of not operation must be a boolean type", ExpressionsExceptionType.TypeMismatch); } type = typeof(bool); break; case ExpressionType.BitwiseNot: if (!TypeUtil.IsInteger(operand.Type)) { throw new ExpressionsException( "Cannot not bitwise not boolean types", ExpressionsExceptionType.TypeMismatch ); } type = operand.Type; break; case ExpressionType.Not: if (TypeUtil.IsInteger(operand.Type)) { type = operand.Type; } else { if (operand.Type != typeof(bool)) { throw new ExpressionsException("Operand of not operation must be a boolean type", ExpressionsExceptionType.TypeMismatch); } type = typeof(bool); } break; default: throw new InvalidOperationException(); } return(new Expressions.UnaryExpression(operand, type, unaryExpression.Type)); }
public IExpression BinaryExpression(Ast.BinaryExpression binaryExpression) { // In expressions are converted to method calls. if (binaryExpression.Type == ExpressionType.In) { return(BinaryInExpression(binaryExpression)); } // We need to do this here and not in the conversion phase because // we need the return type of the method to fully bind the tree. var left = binaryExpression.Left.Accept(this); var right = binaryExpression.Right.Accept(this); string operatorName = null; switch (binaryExpression.Type) { case ExpressionType.Add: operatorName = "op_Addition"; break; case ExpressionType.Divide: operatorName = "op_Division"; break; case ExpressionType.Multiply: operatorName = "op_Multiply"; break; case ExpressionType.Subtract: operatorName = "op_Subtraction"; break; case ExpressionType.Equals: operatorName = "op_Equality"; break; case ExpressionType.NotEquals: operatorName = "op_Inequality"; break; case ExpressionType.Greater: operatorName = "op_GreaterThan"; break; case ExpressionType.GreaterOrEquals: operatorName = "op_GreaterThanOrEqual"; break; case ExpressionType.Less: operatorName = "op_LessThan"; break; case ExpressionType.LessOrEquals: operatorName = "op_LessThanOrEqual"; break; case ExpressionType.ShiftLeft: operatorName = "op_LeftShift"; break; case ExpressionType.ShiftRight: operatorName = "op_RightShift"; break; case ExpressionType.Modulo: operatorName = "op_Modulus"; break; case ExpressionType.LogicalAnd: operatorName = "op_LogicalAnd"; break; case ExpressionType.AndBoth: operatorName = "op_LogicalAnd"; break; case ExpressionType.LogicalOr: operatorName = "op_LogicalOr"; break; case ExpressionType.OrBoth: operatorName = "op_LogicalOr"; break; case ExpressionType.BitwiseAnd: operatorName = "op_BitwiseAnd"; break; case ExpressionType.BitwiseOr: operatorName = "op_BitwiseOr"; break; case ExpressionType.And: if (left.Type == typeof(bool) && right.Type == typeof(bool)) { operatorName = "op_LogicalAnd"; } else { operatorName = "op_BitwiseAnd"; } break; case ExpressionType.Or: if (left.Type == typeof(bool) && right.Type == typeof(bool)) { operatorName = "op_LogicalOr"; } else { operatorName = "op_BitwiseOr"; } break; case ExpressionType.Xor: operatorName = "op_ExclusiveOr"; break; } if (operatorName != null) { var method = _resolver.FindOperatorMethod( operatorName, new[] { left.Type, right.Type }, null, new[] { left.Type, right.Type }, new[] { left is Expressions.Constant && ((Expressions.Constant)left).Value == null, right is Expressions.Constant && ((Expressions.Constant)right).Value == null } ); if (method != null) { return(new Expressions.MethodCall( new TypeAccess(typeof(string)), method, new[] { left, right } )); } } Type commonType; switch (binaryExpression.Type) { case ExpressionType.ShiftLeft: case ExpressionType.ShiftRight: if (!TypeUtil.IsInteger(left.Type)) { throw new ExpressionsException("Left operand of shift operations must be of an integer type", ExpressionsExceptionType.TypeMismatch); } if (right.Type != typeof(int) && right.Type != typeof(byte)) { throw new ExpressionsException("Right operand of shift operations must be integer or byte type", ExpressionsExceptionType.TypeMismatch); } commonType = left.Type; break; case ExpressionType.Power: commonType = typeof(double); break; case ExpressionType.Greater: case ExpressionType.GreaterOrEquals: case ExpressionType.Less: case ExpressionType.LessOrEquals: commonType = ResolveExpressionCommonType(left.Type, right.Type, false, true, false); break; case ExpressionType.Equals: case ExpressionType.NotEquals: case ExpressionType.Compares: case ExpressionType.NotCompares: if (left.Type.IsValueType != right.Type.IsValueType) { throw new ExpressionsException("Cannot resolve expression type", ExpressionsExceptionType.TypeMismatch); } commonType = ResolveExpressionCommonType(left.Type, right.Type, false, false, true); break; default: commonType = ResolveExpressionCommonType(left.Type, right.Type, binaryExpression.Type == ExpressionType.Add, false, false); break; } var type = ResolveExpressionType(left.Type, right.Type, commonType, binaryExpression.Type); var expressionType = binaryExpression.Type; if (type != typeof(bool)) { if (expressionType == ExpressionType.AndBoth) { expressionType = ExpressionType.BitwiseAnd; } else if (expressionType == ExpressionType.OrBoth) { expressionType = ExpressionType.BitwiseOr; } } return(new Expressions.BinaryExpression(left, right, expressionType, type, commonType)); }