예제 #1
0
        public Expression CompileUnOp(AstUnary uo)
        {
            var operand = CompileExpression(uo.Operand);

            if (operand.IsInvalid)
            {
                return(Expression.Invalid);
            }

            switch (uo.Type)
            {
            case AstUnaryType.IncreasePrefix:
            case AstUnaryType.DecreasePrefix:
            case AstUnaryType.IncreasePostfix:
            case AstUnaryType.DecreasePostfix:
                return(!operand.ReturnType.IsIntegralType && !operand.ReturnType.IsFloatingPointType
                        ? Error(uo.Source, ErrorCode.E2063, "Incremental operators can only be used on integers")
                        : new FixOp(uo.Source, (FixOpType)uo.Type, operand));
            }

            var args = new[] { operand };
            var opOp = uo.Type.ToSymbol();
            var op   = TryResolveOperatorOverload(uo.Source, NameResolver.GetTypeOperators(operand.ReturnType, opOp), args);

            return(op != null
                ? new CallUnOp(uo.Source, op, args[0])
                : Error(uo.Source, ErrorCode.E2065, operand.ReturnType.Quote() + " has no operators matching the argument list"));
        }
예제 #2
0
        Expression CompileBinOp(Source src, AstBinaryType binOp, Expression left, Expression right)
        {
            if (left.IsInvalid || right.IsInvalid)
            {
                return(Expression.Invalid);
            }

            if ((left.ReturnType is NullType || left.ReturnType is MethodGroupType) && right.ReturnType.IsReferenceType)
            {
                var leftCast = TryCompileImplicitCast(src, right.ReturnType, left);
                if (leftCast != null)
                {
                    left = leftCast;
                }
            }
            else if ((right.ReturnType is NullType || right.ReturnType is MethodGroupType) && left.ReturnType.IsReferenceType)
            {
                var rightCast = TryCompileImplicitCast(src, left.ReturnType, right);
                if (rightCast != null)
                {
                    right = rightCast;
                }
            }

            var args = new[] { left, right };
            var opOp = binOp.ToSymbol();
            var op   = TryResolveOperatorOverload(src,
                                                  NameResolver.GetTypeOperators(left.ReturnType, right.ReturnType, opOp),
                                                  args);

            if (op != null)
            {
                return(new CallBinOp(src, op, args[0], args[1]));
            }

            switch (binOp)
            {
            case AstBinaryType.LogAnd:
            case AstBinaryType.LogOr:
            {
                left  = CompileImplicitCast(src, Essentials.Bool, left);
                right = CompileImplicitCast(src, Essentials.Bool, right);
                return(new BranchOp(
                           src, Essentials.Bool,
                           binOp == AstBinaryType.LogAnd
                            ? BranchType.And
                            : BranchType.Or,
                           left, right));
            }

            case AstBinaryType.Null:
            {
                if (left.ReturnType.IsNull)
                {
                    return(right);
                }
                if (!left.ReturnType.IsReferenceType)
                {
                    return(Error(src, ErrorCode.E2015, "'??' cannot be used on operand of type " + left.ReturnType.Quote() + " because it is not a reference type"));
                }

                right = CompileImplicitCast(src, left.ReturnType, right);
                return(new NullOp(src, left, right));
            }

            case AstBinaryType.Equal:
            case AstBinaryType.NotEqual:
            {
                if (left.ReturnType.IsReferenceType && right.ReturnType.IsReferenceType)
                {
                    return(new ReferenceOp(src, Essentials.Bool, binOp == AstBinaryType.Equal ? EqualityType.Equal : EqualityType.NotEqual, left, right));
                }
                break;
            }

            case AstBinaryType.Sequence:
                return(new SequenceOp(left, right));
            }

            return(Error(src, ErrorCode.E2016, left.ReturnType.Quote() + " has no operators " + binOp.ToSymbol().Quote() + " matching the argument list"));
        }