/// <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" ) )); }
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)); }
/// <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); }
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); } }
/// <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)); }
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); }