예제 #1
0
        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));
        }