예제 #1
0
        /// <summary>
        /// Repeats a string.
        /// </summary>
        private NodeBase StringExpand(Context ctx)
        {
            var tmpString = ctx.Scope.DeclareImplicit(ctx, typeof(string), false);
            var tmpSb     = ctx.Scope.DeclareImplicit(ctx, typeof(StringBuilder), false);
            var tmpIdx    = ctx.Scope.DeclareImplicit(ctx, RightOperand.Resolve(ctx), false);

            // var sb = new StringBuilder();
            // for _ in 1..N do
            //    sb.Append (str)
            // str.ToString ()
            return(Expr.Block(
                       Expr.Let(tmpString, LeftOperand),
                       Expr.Let(tmpSb, Expr.New(typeof(StringBuilder))),
                       Expr.For(
                           tmpIdx,
                           Expr.Int(1),
                           RightOperand,
                           Expr.Block(
                               Expr.Invoke(
                                   Expr.Get(tmpSb),
                                   "Append",
                                   Expr.Get(tmpString)
                                   )
                               )
                           ),
                       Expr.Invoke(
                           Expr.Get(tmpSb),
                           "ToString"
                           )
                       ));
        }
예제 #2
0
        protected override NodeBase expand(Context ctx, bool mustReturn)
        {
            if (Resolve(ctx).IsNullableType())
            {
                var leftNullable  = LeftOperand.Resolve(ctx).IsNullableType();
                var rightNullable = RightOperand.Resolve(ctx).IsNullableType();
                if (leftNullable && rightNullable)
                {
                    return(Expr.If(
                               Expr.And(
                                   Expr.GetMember(LeftOperand, "HasValue"),
                                   Expr.GetMember(RightOperand, "HasValue")
                                   ),
                               Expr.Block(
                                   recreateSelfWithArgs(
                                       Expr.GetMember(LeftOperand, "Value"),
                                       Expr.GetMember(RightOperand, "Value")
                                       )
                                   ),
                               Expr.Block(Expr.Null())
                               ));
                }

                if (leftNullable)
                {
                    return(Expr.If(
                               Expr.GetMember(LeftOperand, "HasValue"),
                               Expr.Block(
                                   recreateSelfWithArgs(
                                       Expr.GetMember(LeftOperand, "Value"),
                                       RightOperand
                                       )
                                   ),
                               Expr.Block(Expr.Null())
                               ));
                }

                if (rightNullable)
                {
                    return(Expr.If(
                               Expr.GetMember(RightOperand, "HasValue"),
                               Expr.Block(
                                   recreateSelfWithArgs(
                                       LeftOperand,
                                       Expr.GetMember(RightOperand, "Value")
                                       )
                                   ),
                               Expr.Block(Expr.Null())
                               ));
                }
            }

            return(base.expand(ctx, mustReturn));
        }
예제 #3
0
        /// <summary>
        /// Loads both arguments and converts them to the biggest common type.
        /// </summary>
        protected void loadAndConvertNumerics(Context ctx, Type type = null)
        {
            var left  = LeftOperand.Resolve(ctx);
            var right = RightOperand.Resolve(ctx);

            if (type == null)
            {
                type = TypeExtensions.GetNumericOperationType(left, right);
            }

            Expr.Cast(LeftOperand, type).Emit(ctx, true);
            Expr.Cast(RightOperand, type).Emit(ctx, true);
        }
예제 #4
0
        protected override void EmitOperator(Context ctx)
        {
            var leftType   = LeftOperand.Resolve(ctx);
            var rightType  = RightOperand.Resolve(ctx);
            var isEquality = Kind == ComparisonOperatorKind.Equals || Kind == ComparisonOperatorKind.NotEquals;

            if (!CanCompare(leftType, rightType, isEquality))
            {
                Error(CompilerMessages.TypesIncomparable, leftType, rightType);
            }

            if (isEquality)
            {
                EmitEqualityComparison(ctx, leftType, rightType);
            }
            else
            {
                EmitRelation(ctx, leftType, rightType);
            }
        }
예제 #5
0
        /// <summary>
        /// Extra hint for function composition.
        /// </summary>
        protected override Type ResolveInternal(Context ctx, bool mustReturn)
        {
            var leftType = LeftOperand.Resolve(ctx);

            // check if the shift operator is used for function composition
            if (leftType.IsCallableType())
            {
                // add left operand's return type as hint to right operand
                var leftDelegate = ReflectionHelper.WrapDelegate(leftType);
                if (RightOperand is GetMemberNode)
                {
                    var mbr = RightOperand as GetMemberNode;
                    if (mbr.TypeHints == null || mbr.TypeHints.Count == 0)
                    {
                        mbr.TypeHints = new List <TypeSignature> {
                            leftDelegate.ReturnType.FullName
                        }
                    }
                    ;
                }
                else if (RightOperand is LambdaNode)
                {
                    var lambda = RightOperand as LambdaNode;
                    lambda.Resolve(ctx);
                    if (lambda.MustInferArgTypes)
                    {
                        lambda.SetInferredArgumentTypes(new[] { leftDelegate.ReturnType });
                    }
                }

                var rightType = RightOperand.Resolve(ctx);

                if (!ReflectionHelper.CanCombineDelegates(leftType, rightType))
                {
                    Error(Translations.CompilerMessages.DelegatesNotCombinable, leftType, rightType);
                }
            }

            // resolve as a possibly overloaded operator
            return(base.ResolveInternal(ctx, mustReturn));
        }
예제 #6
0
        protected override Type resolve(Context ctx, bool mustReturn)
        {
            var leftType  = LeftOperand.Resolve(ctx);
            var rightType = RightOperand.Resolve(ctx);

            var result = resolveOperatorType(ctx, leftType, rightType);

            if (result != null)
            {
                return(result);
            }

            if (OverloadedMethodName != null)
            {
                try
                {
                    _OverloadedMethod = ctx.ResolveMethod(leftType, OverloadedMethodName, new[] { leftType, rightType });
                }
                catch
                {
                    try
                    {
                        _OverloadedMethod = ctx.ResolveMethod(rightType, OverloadedMethodName, new[] { leftType, rightType });
                    }
                    catch { }
                }

                // cannot be generic
                if (_OverloadedMethod != null)
                {
                    return(_OverloadedMethod.ReturnType);
                }
            }

            if (IsNumericOperator)
            {
                if (leftType.IsNullableType() || rightType.IsNullableType())
                {
                    var leftNullable  = leftType.IsNullableType() ? leftType.GetGenericArguments()[0] : leftType;
                    var rightNullable = rightType.IsNullableType() ? rightType.GetGenericArguments()[0] : rightType;

                    var commonNumericType = TypeExtensions.GetNumericOperationType(leftNullable, rightNullable);
                    if (commonNumericType == null)
                    {
                        error(CompilerMessages.OperatorTypesSignednessMismatch);
                    }

                    return(typeof(Nullable <>).MakeGenericType(commonNumericType));
                }

                if (leftType.IsNumericType() && rightType.IsNumericType())
                {
                    var commonNumericType = TypeExtensions.GetNumericOperationType(leftType, rightType);
                    if (commonNumericType == null)
                    {
                        error(CompilerMessages.OperatorTypesSignednessMismatch);
                    }

                    return(commonNumericType);
                }
            }

            error(this, CompilerMessages.OperatorBinaryTypesMismatch, OperatorRepresentation, leftType, rightType);
            return(null);
        }