Example #1
0
        private DataType InferUnaryExpressionType(UnaryExpressionSyntax unaryExpression)
        {
            var operandType = InferExpressionType(unaryExpression.Operand);
            var @operator   = unaryExpression.Operator;

            // If either is unknown, then we can't know whether there is a a problem
            // (technically not true, for example, we could know that one arg should
            // be a bool and isn't)
            if (operandType == DataType.Unknown)
            {
                return(unaryExpression.Type = DataType.Unknown);
            }

            bool typeError;

            switch (@operator)
            {
            case UnaryOperator.Not:
                typeError            = operandType != DataType.Bool;
                unaryExpression.Type = DataType.Bool;
                break;

            case UnaryOperator.At:
                typeError = false;     // TODO check that the expression can have a pointer taken
                if (operandType is Metatype)
                {
                    unaryExpression.Type = DataType.Type;     // constructing a type
                }
                else
                {
                    unaryExpression.Type = new PointerType(operandType);     // taking the address of something
                }
                break;

            case UnaryOperator.Question:
                typeError            = false; // TODO check that the expression can have a pointer taken
                unaryExpression.Type = new PointerType(operandType);
                break;

            case UnaryOperator.Caret:
                switch (operandType)
                {
                case PointerType pointerType:
                    unaryExpression.Type = pointerType.Referent;
                    typeError            = false;
                    break;

                default:
                    unaryExpression.Type = DataType.Unknown;
                    typeError            = true;
                    break;
                }
                break;

            case UnaryOperator.Minus:
                switch (operandType)
                {
                case IntegerConstantType integerType:
                    typeError            = false;
                    unaryExpression.Type = integerType;
                    break;

                case SizedIntegerType sizedIntegerType:
                    typeError            = false;
                    unaryExpression.Type = sizedIntegerType;
                    break;

                default:
                    unaryExpression.Type = DataType.Unknown;
                    typeError            = true;
                    break;
                }
                break;

            default:
                throw NonExhaustiveMatchException.ForEnum(@operator);
            }
            if (typeError)
            {
                diagnostics.Add(TypeError.OperatorCannotBeAppliedToOperandOfType(file,
                                                                                 unaryExpression.Span, @operator, operandType));
            }

            return(unaryExpression.Type);
        }