public IType Resolve(ITypeResolveContext context)
 {
     foreach (var asm in context.Compilation.Assemblies)
     {
         foreach (var attr in asm.AssemblyAttributes.Where(a => a.AttributeType.FullName == XmlnsDefinitionAttribute && a.PositionalArguments.Count == 2))
         {
             ConstantResolveResult crr  = attr.PositionalArguments[0] as ConstantResolveResult;
             ConstantResolveResult crr2 = attr.PositionalArguments[1] as ConstantResolveResult;
             if (crr == null || crr2 == null)
             {
                 continue;
             }
             string namespaceName = crr2.ConstantValue as string;
             if (xmlNamespace.Equals(crr.ConstantValue as string, StringComparison.OrdinalIgnoreCase) && namespaceName != null)
             {
                 ITypeDefinition td = asm.GetTypeDefinition(namespaceName, localName, 0);
                 if (td != null)
                 {
                     return(td);
                 }
             }
         }
     }
     return(new UnknownType(null, localName, 0));
 }
Exemple #2
0
        public JsNode VisitConstantResolveResult(ConstantResolveResult res)
        {
            var nodes = res.GetNodes();

            if (res.Type is DefaultTypeParameter)
            {
                return(Js.Member("Default").Invoke(SkJs.EntityTypeRefToMember(res.Type)));
            }
            if (res.Type != null && res.Type.Kind == TypeKind.Enum)
            {
                var enumMembers = res.Type.GetFields();
                var me          = enumMembers.Where(t => (t.ConstantValue != null) && t.ConstantValue.Equals(res.ConstantValue)).FirstOrDefault();
                if (me != null)
                {
                    return(Visit(me.AccessSelf()));//.Access().Member(c.CreateTypeRef(en), defaultEnumMember);
                }
                //TODO:
                //return Visit(JsTypeImporter.GetValueTypeInitializer(res.Type, Project));
            }
            //var nodes = res.GetNodes();
            //if (nodes.IsNotNullOrEmpty())
            //{
            //    var node = nodes[0];
            //    if (node != null && node is PrimitiveExpression)
            //    {
            //        var node2 = Visit(node); //use literal value instead
            //        return node2;
            //    }
            //}
            return(Js.Value(res.ConstantValue));
        }
Exemple #3
0
        public JsNode VisitConstantResolveResult(ConstantResolveResult res)
        {
            if (res.Type is DefaultTypeParameter)
            {
                return(Js.Member("Default").Invoke(SkJs.EntityTypeRefToMember(res.Type)));
            }
            if (res.Type != null && res.Type.Kind == TypeKind.Enum)
            {
                var enumMembers = res.Type.GetFields();
                var me          = enumMembers.Where(t => (t.ConstantValue != null) && t.ConstantValue.Equals(res.ConstantValue)).FirstOrDefault();
                if (me != null)
                {
                    return(Visit(me.AccessSelf()));//.Access().Member(c.CreateTypeRef(en), defaultEnumMember);
                }
                //TODO:
                //return Visit(JsTypeImporter.GetValueTypeInitializer(res.Type, Project));
            }
            var nodes = res.GetNodes();

            if (nodes.IsNotNullOrEmpty())
            {
                if (nodes[0] != null)
                {
                    bool isPrimitiveExpr = nodes[0] is PrimitiveExpression;
                    if (!isPrimitiveExpr)
                    {
                        return(Js.Value(res.ConstantValue, string.Format(" /* {0} */", nodes[0].ToString())));
                    }
                }
            }
            return(Js.Value(res.ConstantValue));
        }
Exemple #4
0
        private static IList <IAttribute> CreateMockAttributes(IEnumerable <Expression <Func <System.Attribute> > > attributes)
        {
            var result = new List <IAttribute>();

            if (attributes != null)
            {
                foreach (var attrExpression in attributes)
                {
                    var attr = new Mock <IAttribute>(MockBehavior.Strict);
                    var body = (NewExpression)attrExpression.Body;
                    attr.SetupGet(_ => _.AttributeType).Returns(CreateMockTypeDefinition(body.Type.FullName, null));
                    var posArgs = new List <ResolveResult>();
                    foreach (var argExpression in body.Arguments)
                    {
                        var argType = new Mock <IType>(MockBehavior.Strict);
                        argType.SetupGet(_ => _.Namespace).Returns(argExpression.Type.Namespace);
                        argType.SetupGet(_ => _.Name).Returns(argExpression.Type.Name);
                        argType.SetupGet(_ => _.FullName).Returns(argExpression.Type.FullName);
                        var arg = new ConstantResolveResult(argType.Object, ((ConstantExpression)argExpression).Value);
                        posArgs.Add(arg);
                    }
                    attr.SetupGet(_ => _.PositionalArguments).Returns(posArgs);

                    if (body.Members != null && body.Members.Count > 0)
                    {
                        throw new InvalidOperationException("Named attribute args are not supported");
                    }

                    attr.SetupGet(_ => _.NamedArguments).Returns(new KeyValuePair <IMember, ResolveResult> [0]);

                    result.Add(attr.Object);
                }
            }
            return(result);
        }
Exemple #5
0
 private void ProcessPositionalArgs(IList <ResolveResult> args)
 {
     if (args.Count == 0)
     {
         return;
     }
     Console.WriteLine("attribute.PositionalArguments :");
     for (Int32 index = 0; index < args.Count; ++index)
     {
         ResolveResult argResult = args[index];
         Console.Write("index = {0}, type = {1}", index, argResult.GetType());
         if (argResult is ConstantResolveResult)
         {
             ConstantResolveResult constResult = (ConstantResolveResult)argResult;
             Console.Write(", value = {0}", constResult.ConstantValue);
         }
         if (argResult is MemberResolveResult)
         {
             MemberResolveResult memberResult = (MemberResolveResult)argResult;
             IMember             member       = memberResult.Member;
             Console.Write(", value = {0}, memberKind = {1}, typeKind = {2}", member.Name, member.SymbolKind, memberResult.Type.Kind);
         }
         Console.WriteLine();
     }
 }
        public void NullableConversion_BasedOnImplicitEnumerationConversion()
        {
            ResolveResult zero = new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), 0);
            ResolveResult one  = new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), 1);

            Assert.AreEqual(C.EnumerationConversion(true, true), conversions.ExplicitConversion(zero, compilation.FindType(typeof(StringComparison?))));
            Assert.AreEqual(C.EnumerationConversion(false, true), conversions.ExplicitConversion(one, compilation.FindType(typeof(StringComparison?))));
        }
 public object VisitConstantResolveResult(ConstantResolveResult res)
 {
     if (res.Type.Kind == TypeKind.Enum)
     {
         var value = Enum.ToObject(res.Type.GetMirroredClrType(), res.ConstantValue);
         return(value);
     }
     return(res.ConstantValue);
 }
        bool AreEqualConstants(ConstantResolveResult c1, ConstantResolveResult c2)
        {
            if (c1 == null || c2 == null)
            {
                return(false);
            }
            CSharpResolver r = new CSharpResolver(resolveVisitor.TypeResolveContext, resolveVisitor.CancellationToken);
            ResolveResult  c = r.ResolveBinaryOperator(BinaryOperatorType.Equality, c1, c2);

            return(c.IsCompileTimeConstant && (c.ConstantValue as bool?) == true);
        }
        public override IList <ResolveResult> GetArgumentsForCall()
        {
            ResolveResult[]      results         = new ResolveResult[Member.Parameters.Count];
            List <ResolveResult> paramsArguments = IsExpandedForm ? new List <ResolveResult>() : null;

            // map arguments to parameters:
            for (int i = 0; i < Arguments.Count; i++)
            {
                int mappedTo;
                if (argumentToParameterMap != null)
                {
                    mappedTo = argumentToParameterMap[i];
                }
                else
                {
                    mappedTo = IsExpandedForm ? Math.Min(i, results.Length - 1) : i;
                }

                if (mappedTo >= 0 && mappedTo < results.Length)
                {
                    if (IsExpandedForm && mappedTo == results.Length - 1)
                    {
                        paramsArguments.Add(Arguments[i]);
                    }
                    else
                    {
                        results[mappedTo] = Arguments[i];
                    }
                }
            }
            if (IsExpandedForm)
            {
                results[results.Length - 1] = new ArrayCreateResolveResult(Member.Parameters.Last().Type, null, paramsArguments.ToArray());
            }

            for (int i = 0; i < results.Length; i++)
            {
                if (results[i] == null)
                {
                    if (Member.Parameters[i].IsOptional)
                    {
                        results[i] = new ConstantResolveResult(Member.Parameters[i].Type, Member.Parameters[i].ConstantValue);
                    }
                    else
                    {
                        results[i] = ErrorResolveResult.UnknownError;
                    }
                }
            }

            return(results);
        }
        /// <summary>
        /// Evaluates an expression.
        /// </summary>
        /// <returns>The value of the constant boolean expression; or null if the value is not a constant boolean expression.</returns>
        bool?EvaluateCondition(Expression expr)
        {
            ConstantResolveResult rr = EvaluateConstant(expr);

            if (rr != null)
            {
                return(rr.ConstantValue as bool?);
            }
            else
            {
                return(null);
            }
        }
Exemple #11
0
        private bool NeedExportDefaultValueExpression(ConstantResolveResult res)
        {
            // 值类型 default 处理
            // 但是传给 C# 的时候,也许传 null 会更好
            if (res.Type.Kind == TypeKind.Struct)
            {
                // 过滤 Nullable
                if (res.Type.FullName != "System.Nullable")
                {
                    return(true);
                }
            }

            return(false);
        }
Exemple #12
0
        public JNode VisitConstantResolveResult(ConstantResolveResult res)
        {
            var nodes = res.GetNodes();

            if (res.Type is DefaultTypeParameter)
            {
                return(J.Member("Default").Invoke(JNaming.JAccess(res.Type)));
            }
            if (res.Type != null && res.Type.Kind == TypeKind.Enum)
            {
                return(Visit(JTypeImporter.GetValueTypeInitializer(res.Type, Compiler)));
            }
            //var nodes = res.GetNodes();
            //if (nodes.IsNotNullOrEmpty())
            //{
            //    var node = nodes[0];
            //    if (node != null && node is PrimitiveExpression)
            //    {
            //        var node2 = Visit(node); //use literal value instead
            //        return node2;
            //    }
            //}
            return(J.Value(res.ConstantValue));
        }
		public void NullableConversion_BasedOnImplicitEnumerationConversion()
		{
			ResolveResult zero = new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), 0);
			ResolveResult one = new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), 1);
			Assert.AreEqual(C.EnumerationConversion(true, true), conversions.ExplicitConversion(zero, compilation.FindType(typeof(StringComparison?))));
			Assert.AreEqual(C.EnumerationConversion(false, true), conversions.ExplicitConversion(one, compilation.FindType(typeof(StringComparison?))));
		}
		int BetterConversion(object value, Type t1, Type t2)
		{
			IType fromType = value.GetType().ToTypeReference().Resolve(ctx);
			ConstantResolveResult crr = new ConstantResolveResult(fromType, value);
			IType t1Type = t1.ToTypeReference().Resolve(ctx);
			IType t2Type = t2.ToTypeReference().Resolve(ctx);
			return conversions.BetterConversion(crr, t1Type, t2Type);
		}
 public virtual TResult VisitConstantResolveResult(ConstantResolveResult rr, TData data)
 {
     VisitChildResolveResults(rr, data);
     return(default(TResult));
 }
Exemple #16
0
 public void EnumerationConversion()
 {
     ResolveResult zero = new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), 0);
     ResolveResult one = new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), 1);
     C implicitEnumerationConversion = C.EnumerationConversion(true, false);
     Assert.AreEqual(implicitEnumerationConversion, conversions.ImplicitConversion(zero, compilation.FindType(typeof(StringComparison))));
     Assert.AreEqual(C.None, conversions.ImplicitConversion(one, compilation.FindType(typeof(StringComparison))));
 }
Exemple #17
0
 bool IntegerLiteralConversion(object value, Type to)
 {
     IType fromType = compilation.FindType(value.GetType());
     ConstantResolveResult crr = new ConstantResolveResult(fromType, value);
     IType to2 = compilation.FindType(to);
     return conversions.ImplicitConversion(crr, to2).IsValid;
 }
Exemple #18
0
 int BetterConversion(object value, Type t1, Type t2)
 {
     IType fromType = compilation.FindType(value.GetType());
     ConstantResolveResult crr = new ConstantResolveResult(fromType, value);
     IType t1Type = compilation.FindType(t1);
     IType t2Type = compilation.FindType(t2);
     return conversions.BetterConversion(crr, t1Type, t2Type);
 }
 public override DefiniteAssignmentStatus VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, DefiniteAssignmentStatus data)
 {
     if (binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalAnd)
     {
         // Handle constant left side of && expressions (not in the C# spec, but done by the MS compiler)
         bool?cond = analysis.EvaluateCondition(binaryOperatorExpression.Left);
         if (cond == true)
         {
             return(binaryOperatorExpression.Right.AcceptVisitor(this, data));                        // right operand gets evaluated unconditionally
         }
         else if (cond == false)
         {
             return(data);                        // right operand never gets evaluated
         }
         // C# 4.0 spec: §5.3.3.24 Definite Assignment for && expressions
         DefiniteAssignmentStatus afterLeft = binaryOperatorExpression.Left.AcceptVisitor(this, data);
         DefiniteAssignmentStatus beforeRight;
         if (afterLeft == DefiniteAssignmentStatus.AssignedAfterTrueExpression)
         {
             beforeRight = DefiniteAssignmentStatus.DefinitelyAssigned;
         }
         else if (afterLeft == DefiniteAssignmentStatus.AssignedAfterFalseExpression)
         {
             beforeRight = DefiniteAssignmentStatus.PotentiallyAssigned;
         }
         else
         {
             beforeRight = afterLeft;
         }
         DefiniteAssignmentStatus afterRight = binaryOperatorExpression.Right.AcceptVisitor(this, beforeRight);
         if (afterLeft == DefiniteAssignmentStatus.DefinitelyAssigned)
         {
             return(DefiniteAssignmentStatus.DefinitelyAssigned);
         }
         else if (afterRight == DefiniteAssignmentStatus.DefinitelyAssigned && afterLeft == DefiniteAssignmentStatus.AssignedAfterFalseExpression)
         {
             return(DefiniteAssignmentStatus.DefinitelyAssigned);
         }
         else if (afterRight == DefiniteAssignmentStatus.DefinitelyAssigned || afterRight == DefiniteAssignmentStatus.AssignedAfterTrueExpression)
         {
             return(DefiniteAssignmentStatus.AssignedAfterTrueExpression);
         }
         else if (afterLeft == DefiniteAssignmentStatus.AssignedAfterFalseExpression && afterRight == DefiniteAssignmentStatus.AssignedAfterFalseExpression)
         {
             return(DefiniteAssignmentStatus.AssignedAfterFalseExpression);
         }
         else
         {
             return(DefiniteAssignmentStatus.PotentiallyAssigned);
         }
     }
     else if (binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalOr)
     {
         // C# 4.0 spec: §5.3.3.25 Definite Assignment for || expressions
         bool?cond = analysis.EvaluateCondition(binaryOperatorExpression.Left);
         if (cond == false)
         {
             return(binaryOperatorExpression.Right.AcceptVisitor(this, data));                        // right operand gets evaluated unconditionally
         }
         else if (cond == true)
         {
             return(data);                        // right operand never gets evaluated
         }
         DefiniteAssignmentStatus afterLeft = binaryOperatorExpression.Left.AcceptVisitor(this, data);
         DefiniteAssignmentStatus beforeRight;
         if (afterLeft == DefiniteAssignmentStatus.AssignedAfterTrueExpression)
         {
             beforeRight = DefiniteAssignmentStatus.PotentiallyAssigned;
         }
         else if (afterLeft == DefiniteAssignmentStatus.AssignedAfterFalseExpression)
         {
             beforeRight = DefiniteAssignmentStatus.DefinitelyAssigned;
         }
         else
         {
             beforeRight = afterLeft;
         }
         DefiniteAssignmentStatus afterRight = binaryOperatorExpression.Right.AcceptVisitor(this, beforeRight);
         if (afterLeft == DefiniteAssignmentStatus.DefinitelyAssigned)
         {
             return(DefiniteAssignmentStatus.DefinitelyAssigned);
         }
         else if (afterRight == DefiniteAssignmentStatus.DefinitelyAssigned && afterLeft == DefiniteAssignmentStatus.AssignedAfterTrueExpression)
         {
             return(DefiniteAssignmentStatus.DefinitelyAssigned);
         }
         else if (afterRight == DefiniteAssignmentStatus.DefinitelyAssigned || afterRight == DefiniteAssignmentStatus.AssignedAfterFalseExpression)
         {
             return(DefiniteAssignmentStatus.AssignedAfterFalseExpression);
         }
         else if (afterLeft == DefiniteAssignmentStatus.AssignedAfterTrueExpression && afterRight == DefiniteAssignmentStatus.AssignedAfterTrueExpression)
         {
             return(DefiniteAssignmentStatus.AssignedAfterTrueExpression);
         }
         else
         {
             return(DefiniteAssignmentStatus.PotentiallyAssigned);
         }
     }
     else if (binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing)
     {
         // C# 4.0 spec: §5.3.3.27 Definite assignment for ?? expressions
         ConstantResolveResult crr = analysis.EvaluateConstant(binaryOperatorExpression.Left);
         if (crr != null && crr.ConstantValue == null)
         {
             return(binaryOperatorExpression.Right.AcceptVisitor(this, data));
         }
         DefiniteAssignmentStatus status = CleanSpecialValues(binaryOperatorExpression.Left.AcceptVisitor(this, data));
         binaryOperatorExpression.Right.AcceptVisitor(this, status);
         return(status);
     }
     else
     {
         // use default logic for other operators
         return(VisitChildren(binaryOperatorExpression, data));
     }
 }
Exemple #20
0
        SwitchStatement TranslateSwitch(BlockContainer switchContainer, SwitchInstruction inst)
        {
            Debug.Assert(switchContainer.EntryPoint.IncomingEdgeCount == 1);
            var oldBreakTarget = breakTarget;

            breakTarget = switchContainer;             // 'break' within a switch would only leave the switch
            var oldCaseLabelMapping = caseLabelMapping;

            caseLabelMapping = new Dictionary <Block, ConstantResolveResult>();

            TranslatedExpression value;
            var strToInt = inst.Value as StringToInt;

            if (strToInt != null)
            {
                value = exprBuilder.Translate(strToInt.Argument);
            }
            else
            {
                value = exprBuilder.Translate(inst.Value);
            }

            // Pick the section with the most labels as default section.
            IL.SwitchSection defaultSection = inst.Sections.First();
            foreach (var section in inst.Sections)
            {
                if (section.Labels.Count() > defaultSection.Labels.Count())
                {
                    defaultSection = section;
                }
            }

            var stmt = new SwitchStatement()
            {
                Expression = value
            };
            Dictionary <IL.SwitchSection, Syntax.SwitchSection> translationDictionary = new Dictionary <IL.SwitchSection, Syntax.SwitchSection>();

            // initialize C# switch sections.
            foreach (var section in inst.Sections)
            {
                // This is used in the block-label mapping.
                ConstantResolveResult firstValueResolveResult;
                var astSection = new Syntax.SwitchSection();
                // Create case labels:
                if (section == defaultSection)
                {
                    astSection.CaseLabels.Add(new CaseLabel());
                    firstValueResolveResult = null;
                }
                else
                {
                    var values = section.Labels.Values.Select(i => CreateTypedCaseLabel(i, value.Type, strToInt?.Map)).ToArray();
                    if (section.HasNullLabel)
                    {
                        astSection.CaseLabels.Add(new CaseLabel(new NullReferenceExpression()));
                        firstValueResolveResult = new ConstantResolveResult(SpecialType.NullType, null);
                    }
                    else
                    {
                        Debug.Assert(values.Length > 0);
                        firstValueResolveResult = values[0];
                    }
                    astSection.CaseLabels.AddRange(values.Select(label => new CaseLabel(exprBuilder.ConvertConstantValue(label, allowImplicitConversion: true))));
                }
                switch (section.Body)
                {
                case Branch br:
                    // we can only inline the block, if all branches are in the switchContainer.
                    if (br.TargetBlock.Parent == switchContainer && switchContainer.Descendants.OfType <Branch>().Where(b => b.TargetBlock == br.TargetBlock).All(b => BlockContainer.FindClosestSwitchContainer(b) == switchContainer))
                    {
                        caseLabelMapping.Add(br.TargetBlock, firstValueResolveResult);
                    }
                    break;

                default:
                    break;
                }
                translationDictionary.Add(section, astSection);
                stmt.SwitchSections.Add(astSection);
            }
            foreach (var section in inst.Sections)
            {
                var astSection = translationDictionary[section];
                switch (section.Body)
                {
                case Branch br:
                    // we can only inline the block, if all branches are in the switchContainer.
                    if (br.TargetBlock.Parent == switchContainer && switchContainer.Descendants.OfType <Branch>().Where(b => b.TargetBlock == br.TargetBlock).All(b => BlockContainer.FindClosestSwitchContainer(b) == switchContainer))
                    {
                        ConvertSwitchSectionBody(astSection, br.TargetBlock);
                    }
                    else
                    {
                        ConvertSwitchSectionBody(astSection, section.Body);
                    }
                    break;

                case Leave leave:
                    if (astSection.CaseLabels.Count == 1 && astSection.CaseLabels.First().Expression.IsNull&& leave.TargetContainer == switchContainer)
                    {
                        stmt.SwitchSections.Remove(astSection);
                        break;
                    }
                    goto default;

                default:
                    ConvertSwitchSectionBody(astSection, section.Body);
                    break;
                }
            }
            if (switchContainer != null)
            {
                // Translate any remaining blocks:
                var lastSectionStatements = stmt.SwitchSections.Last().Statements;
                foreach (var block in switchContainer.Blocks.Skip(1))
                {
                    if (caseLabelMapping.ContainsKey(block))
                    {
                        continue;
                    }
                    lastSectionStatements.Add(new LabelStatement {
                        Label = block.Label
                    });
                    foreach (var nestedInst in block.Instructions)
                    {
                        var nestedStmt = Convert(nestedInst);
                        if (nestedStmt is BlockStatement b)
                        {
                            foreach (var nested in b.Statements)
                            {
                                lastSectionStatements.Add(nested.Detach());
                            }
                        }
                        else
                        {
                            lastSectionStatements.Add(nestedStmt);
                        }
                    }
                    Debug.Assert(block.FinalInstruction.OpCode == OpCode.Nop);
                }
                if (endContainerLabels.TryGetValue(switchContainer, out string label))
                {
                    lastSectionStatements.Add(new LabelStatement {
                        Label = label
                    });
                    lastSectionStatements.Add(new BreakStatement());
                }
            }

            breakTarget      = oldBreakTarget;
            caseLabelMapping = oldCaseLabelMapping;
            return(stmt);
        }
		Conversion IntegerLiteralConversion(object value, Type to)
		{
			IType fromType = value.GetType().ToTypeReference().Resolve(ctx);
			ConstantResolveResult crr = new ConstantResolveResult(fromType, value);
			IType to2 = to.ToTypeReference().Resolve(ctx);
			return conversions.ImplicitConversion(crr, to2);
		}
		public void EnumBitwiseOrWithMissingBaseType()
		{
			var resolver = new CSharpResolver(enumWithMissingBaseType.Compilation);
			var lhs = new ConstantResolveResult(enumWithMissingBaseType, 1);
			var rhs = new ConstantResolveResult(enumWithMissingBaseType, 2);
			var rr = (ConstantResolveResult)resolver.ResolveBinaryOperator(BinaryOperatorType.BitwiseOr, lhs, rhs);
			Assert.AreEqual(enumWithMissingBaseType, rr.Type);
			Assert.AreEqual(3, rr.ConstantValue);
		}
		public override IList<ResolveResult> GetArgumentsForCall()
		{
			ResolveResult[] results = new ResolveResult[Member.Parameters.Count];
			List<ResolveResult> paramsArguments = IsExpandedForm ? new List<ResolveResult>() : null;
			// map arguments to parameters:
			for (int i = 0; i < Arguments.Count; i++) {
				int mappedTo;
				if (argumentToParameterMap != null)
					mappedTo = argumentToParameterMap[i];
				else
					mappedTo = IsExpandedForm ? Math.Min(i, results.Length - 1) : i;
				
				if (mappedTo >= 0 && mappedTo < results.Length) {
					if (IsExpandedForm && mappedTo == results.Length - 1) {
						paramsArguments.Add(Arguments[i]);
					} else {
						var narr = Arguments[i] as NamedArgumentResolveResult;
						if (narr != null)
							results[mappedTo] = narr.Argument;
						else
							results[mappedTo] = Arguments[i];
					}
				}
			}
			if (IsExpandedForm)
				results[results.Length - 1] = new ArrayCreateResolveResult(Member.Parameters.Last().Type, null, paramsArguments.ToArray());
			
			for (int i = 0; i < results.Length; i++) {
				if (results[i] == null) {
					if (Member.Parameters[i].IsOptional) {
						results[i] = new ConstantResolveResult(Member.Parameters[i].Type, Member.Parameters[i].ConstantValue);
					} else {
						results[i] = ErrorResolveResult.UnknownError;
					}
				}
			}
			
			return results;
		}
		public override JsExpression VisitConstantResolveResult(ConstantResolveResult rr, object data) {
			return MakeConstant(rr);
		}
Exemple #25
0
 public virtual object VisitConstantResolveResult(ConstantResolveResult rr, object data)
 {
     VisitChildResolveResults(rr, data);
     return(null);
 }
            public override ControlFlowNode VisitSwitchStatement(SwitchStatement switchStatement, ControlFlowNode data)
            {
                // First, figure out which switch section will get called (if the expression is constant):
                ConstantResolveResult constant                 = builder.EvaluateConstant(switchStatement.Expression);
                SwitchSection         defaultSection           = null;
                SwitchSection         sectionMatchedByConstant = null;

                foreach (SwitchSection section in switchStatement.SwitchSections)
                {
                    foreach (CaseLabel label in section.CaseLabels)
                    {
                        if (label.Expression.IsNull)
                        {
                            defaultSection = section;
                        }
                        else if (constant != null)
                        {
                            ConstantResolveResult labelConstant = builder.EvaluateConstant(label.Expression);
                            if (builder.AreEqualConstants(constant, labelConstant))
                            {
                                sectionMatchedByConstant = section;
                            }
                        }
                    }
                }
                if (constant != null && sectionMatchedByConstant == null)
                {
                    sectionMatchedByConstant = defaultSection;
                }

                int gotoCaseOrDefaultInOuterScope = gotoCaseOrDefault.Count;

                ControlFlowNode end = builder.CreateEndNode(switchStatement, addToNodeList: false);

                breakTargets.Push(end);
                foreach (SwitchSection section in switchStatement.SwitchSections)
                {
                    if (constant == null || section == sectionMatchedByConstant)
                    {
                        HandleStatementList(section.Statements, data);
                    }
                    else
                    {
                        // This section is unreachable: pass null to HandleStatementList.
                        HandleStatementList(section.Statements, null);
                    }
                    // Don't bother connecting the ends of the sections: the 'break' statement takes care of that.
                }
                breakTargets.Pop();
                if (defaultSection == null && sectionMatchedByConstant == null)
                {
                    Connect(data, end);
                }

                if (gotoCaseOrDefault.Count > gotoCaseOrDefaultInOuterScope)
                {
                    // Resolve 'goto case' statements:
                    throw new NotImplementedException();
                }

                builder.nodes.Add(end);
                return(end);
            }
Exemple #27
0
 public override string VisitConstantResolveResult(ConstantResolveResult rr, object data)
 {
     return(MakeConstant(rr));
 }
Exemple #28
0
        public override IList <ResolveResult> GetArgumentsForCall()
        {
            ResolveResult[]      results         = new ResolveResult[Member.Parameters.Count];
            List <ResolveResult> paramsArguments = IsExpandedForm ? new List <ResolveResult>() : null;

            // map arguments to parameters:
            for (int i = 0; i < Arguments.Count; i++)
            {
                int mappedTo;
                if (argumentToParameterMap != null)
                {
                    mappedTo = argumentToParameterMap[i];
                }
                else
                {
                    mappedTo = IsExpandedForm ? Math.Min(i, results.Length - 1) : i;
                }

                if (mappedTo >= 0 && mappedTo < results.Length)
                {
                    if (IsExpandedForm && mappedTo == results.Length - 1)
                    {
                        paramsArguments.Add(Arguments[i]);
                    }
                    else
                    {
                        var narr = Arguments[i] as NamedArgumentResolveResult;
                        if (narr != null)
                        {
                            results[mappedTo] = narr.Argument;
                        }
                        else
                        {
                            results[mappedTo] = Arguments[i];
                        }
                    }
                }
            }
            if (IsExpandedForm)
            {
                IType           arrayType     = Member.Parameters.Last().Type;
                IType           int32         = Member.Compilation.FindType(KnownTypeCode.Int32);
                ResolveResult[] sizeArguments = { new ConstantResolveResult(int32, paramsArguments.Count) };
                results[results.Length - 1] = new ArrayCreateResolveResult(arrayType, sizeArguments, paramsArguments);
            }

            for (int i = 0; i < results.Length; i++)
            {
                if (results[i] == null)
                {
                    if (Member.Parameters[i].IsOptional)
                    {
                        results[i] = new ConstantResolveResult(Member.Parameters[i].Type, Member.Parameters[i].GetConstantValue());
                    }
                    else
                    {
                        results[i] = ErrorResolveResult.UnknownError;
                    }
                }
            }

            return(results);
        }
Exemple #29
0
        public ResolveResult ResolveUnaryOperator(UnaryOperatorType op, ResolveResult expression)
        {
            if (expression.Type.Kind == TypeKind.Dynamic) {
                if (op == UnaryOperatorType.Await) {
                    return new AwaitResolveResult(SpecialType.Dynamic, new DynamicInvocationResolveResult(new DynamicMemberResolveResult(expression, "GetAwaiter"), DynamicInvocationType.Invocation, EmptyList<ResolveResult>.Instance), SpecialType.Dynamic, null, null, null);
                }
                else {
                    return UnaryOperatorResolveResult(SpecialType.Dynamic, op, expression);
                }
            }

            // C# 4.0 spec: §7.3.3 Unary operator overload resolution
            string overloadableOperatorName = GetOverloadableOperatorName(op);
            if (overloadableOperatorName == null) {
                switch (op) {
                    case UnaryOperatorType.Dereference:
                        PointerType p = expression.Type as PointerType;
                        if (p != null)
                            return UnaryOperatorResolveResult(p.ElementType, op, expression);
                        else
                            return ErrorResult;
                    case UnaryOperatorType.AddressOf:
                        return UnaryOperatorResolveResult(new PointerType(expression.Type), op, expression);
                    case UnaryOperatorType.Await: {
                        ResolveResult getAwaiterMethodGroup = ResolveMemberAccess(expression, "GetAwaiter", EmptyList<IType>.Instance, NameLookupMode.InvocationTarget);
                        ResolveResult getAwaiterInvocation = ResolveInvocation(getAwaiterMethodGroup, new ResolveResult[0], argumentNames: null, allowOptionalParameters: false);

                        var lookup = CreateMemberLookup();
                        IMethod getResultMethod;
                        IType awaitResultType;
                        var getResultMethodGroup = lookup.Lookup(getAwaiterInvocation, "GetResult", EmptyList<IType>.Instance, true) as MethodGroupResolveResult;
                        if (getResultMethodGroup != null) {
                            var getResultOR = getResultMethodGroup.PerformOverloadResolution(compilation, new ResolveResult[0], allowExtensionMethods: false, conversions: conversions);
                            getResultMethod = getResultOR.FoundApplicableCandidate ? getResultOR.GetBestCandidateWithSubstitutedTypeArguments() as IMethod : null;
                            awaitResultType = getResultMethod != null ? getResultMethod.ReturnType : SpecialType.UnknownType;
                        }
                        else {
                            getResultMethod = null;
                            awaitResultType = SpecialType.UnknownType;
                        }

                        var isCompletedRR = lookup.Lookup(getAwaiterInvocation, "IsCompleted", EmptyList<IType>.Instance, false);
                        var isCompletedProperty = (isCompletedRR is MemberResolveResult ? ((MemberResolveResult)isCompletedRR).Member as IProperty : null);
                        if (isCompletedProperty != null && (!isCompletedProperty.ReturnType.IsKnownType(KnownTypeCode.Boolean) || !isCompletedProperty.CanGet))
                            isCompletedProperty = null;

                        var interfaceOnCompleted = compilation.FindType(KnownTypeCode.INotifyCompletion).GetMethods().FirstOrDefault(x => x.Name == "OnCompleted");
                        var interfaceUnsafeOnCompleted = compilation.FindType(KnownTypeCode.ICriticalNotifyCompletion).GetMethods().FirstOrDefault(x => x.Name == "UnsafeOnCompleted");

                        IMethod onCompletedMethod = null;
                        var candidates = getAwaiterInvocation.Type.GetMethods().Where(x => x.ImplementedInterfaceMembers.Select(y => y.MemberDefinition).Contains(interfaceUnsafeOnCompleted)).ToList();
                        if (candidates.Count == 0) {
                            candidates = getAwaiterInvocation.Type.GetMethods().Where(x => x.ImplementedInterfaceMembers.Select(y => y.MemberDefinition).Contains(interfaceOnCompleted)).ToList();
                            if (candidates.Count == 1)
                                onCompletedMethod = candidates[0];
                        }
                        else if (candidates.Count == 1) {
                            onCompletedMethod = candidates[0];
                        }

                        return new AwaitResolveResult(awaitResultType, getAwaiterInvocation, getAwaiterInvocation.Type, isCompletedProperty, onCompletedMethod, getResultMethod);
                    }

                    default:
                        throw new ArgumentException("Invalid value for UnaryOperatorType", "op");
                }
            }
            // If the type is nullable, get the underlying type:
            IType type = NullableType.GetUnderlyingType(expression.Type);
            bool isNullable = NullableType.IsNullable(expression.Type);

            // the operator is overloadable:
            OverloadResolution userDefinedOperatorOR = CreateOverloadResolution(new[] { expression });
            foreach (var candidate in GetUserDefinedOperatorCandidates(type, overloadableOperatorName)) {
                userDefinedOperatorOR.AddCandidate(candidate);
            }
            if (userDefinedOperatorOR.FoundApplicableCandidate) {
                return CreateResolveResultForUserDefinedOperator(userDefinedOperatorOR, UnaryOperatorExpression.GetLinqNodeType(op, this.CheckForOverflow));
            }

            expression = UnaryNumericPromotion(op, ref type, isNullable, expression);
            CSharpOperators.OperatorMethod[] methodGroup;
            CSharpOperators operators = CSharpOperators.Get(compilation);
            switch (op) {
                case UnaryOperatorType.Increment:
                case UnaryOperatorType.Decrement:
                case UnaryOperatorType.PostIncrement:
                case UnaryOperatorType.PostDecrement:
                    // C# 4.0 spec: §7.6.9 Postfix increment and decrement operators
                    // C# 4.0 spec: §7.7.5 Prefix increment and decrement operators
                    TypeCode code = ReflectionHelper.GetTypeCode(type);
                    if ((code >= TypeCode.Char && code <= TypeCode.Decimal) || type.Kind == TypeKind.Enum || type.Kind == TypeKind.Pointer)
                        return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable);
                    else
                        return new ErrorResolveResult(expression.Type);
                case UnaryOperatorType.Plus:
                    methodGroup = operators.UnaryPlusOperators;
                    break;
                case UnaryOperatorType.Minus:
                    methodGroup = CheckForOverflow ? operators.CheckedUnaryMinusOperators : operators.UncheckedUnaryMinusOperators;
                    break;
                case UnaryOperatorType.Not:
                    methodGroup = operators.LogicalNegationOperators;
                    break;
                case UnaryOperatorType.BitNot:
                    if (type.Kind == TypeKind.Enum) {
                        if (expression.IsCompileTimeConstant && !isNullable && expression.ConstantValue != null) {
                            // evaluate as (E)(~(U)x);
                            var U = compilation.FindType(expression.ConstantValue.GetType());
                            var unpackedEnum = new ConstantResolveResult(U, expression.ConstantValue);
                            return CheckErrorAndResolveUncheckedCast(expression.Type, ResolveUnaryOperator(op, unpackedEnum));
                        } else {
                            return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable);
                        }
                    } else {
                        methodGroup = operators.BitwiseComplementOperators;
                        break;
                    }
                default:
                    throw new InvalidOperationException();
            }
            OverloadResolution builtinOperatorOR = CreateOverloadResolution(new[] { expression });
            foreach (var candidate in methodGroup) {
                builtinOperatorOR.AddCandidate(candidate);
            }
            CSharpOperators.UnaryOperatorMethod m = (CSharpOperators.UnaryOperatorMethod)builtinOperatorOR.BestCandidate;
            IType resultType = m.ReturnType;
            if (builtinOperatorOR.BestCandidateErrors != OverloadResolutionErrors.None) {
                if (userDefinedOperatorOR.BestCandidate != null) {
                    // If there are any user-defined operators, prefer those over the built-in operators.
                    // It'll be a more informative error.
                    return CreateResolveResultForUserDefinedOperator(userDefinedOperatorOR, UnaryOperatorExpression.GetLinqNodeType(op, this.CheckForOverflow));
                } else if (builtinOperatorOR.BestCandidateAmbiguousWith != null) {
                    // If the best candidate is ambiguous, just use the input type instead
                    // of picking one of the ambiguous overloads.
                    return new ErrorResolveResult(expression.Type);
                } else {
                    return new ErrorResolveResult(resultType);
                }
            } else if (expression.IsCompileTimeConstant && m.CanEvaluateAtCompileTime) {
                object val;
                try {
                    val = m.Invoke(this, expression.ConstantValue);
                } catch (ArithmeticException) {
                    return new ErrorResolveResult(resultType);
                }
                return new ConstantResolveResult(resultType, val);
            } else {
                expression = Convert(expression, m.Parameters[0].Type, builtinOperatorOR.ArgumentConversions[0]);
                return UnaryOperatorResolveResult(resultType, op, expression,
                                                  builtinOperatorOR.BestCandidate is OverloadResolution.ILiftedOperator);
            }
        }
Exemple #30
0
        public ResolveResult ResolveUnaryOperator(UnaryOperatorType op, ResolveResult expression)
        {
            if (SpecialType.Dynamic.Equals(expression.Type))
                return UnaryOperatorResolveResult(SpecialType.Dynamic, op, expression);

            // C# 4.0 spec: §7.3.3 Unary operator overload resolution
            string overloadableOperatorName = GetOverloadableOperatorName(op);
            if (overloadableOperatorName == null) {
                switch (op) {
                    case UnaryOperatorType.Dereference:
                        PointerType p = expression.Type as PointerType;
                        if (p != null)
                            return UnaryOperatorResolveResult(p.ElementType, op, expression);
                        else
                            return ErrorResult;
                    case UnaryOperatorType.AddressOf:
                        return UnaryOperatorResolveResult(new PointerType(expression.Type), op, expression);
                    case UnaryOperatorType.Await:
                        ResolveResult getAwaiterMethodGroup = ResolveMemberAccess(expression, "GetAwaiter", EmptyList<IType>.Instance, true);
                        ResolveResult getAwaiterInvocation = ResolveInvocation(getAwaiterMethodGroup, new ResolveResult[0]);
                        var getResultMethodGroup = CreateMemberLookup().Lookup(getAwaiterInvocation, "GetResult", EmptyList<IType>.Instance, true) as MethodGroupResolveResult;
                        if (getResultMethodGroup != null) {
                            var or = getResultMethodGroup.PerformOverloadResolution(compilation, new ResolveResult[0], allowExtensionMethods: false, conversions: conversions);
                            IType awaitResultType = or.GetBestCandidateWithSubstitutedTypeArguments().ReturnType;
                            return UnaryOperatorResolveResult(awaitResultType, UnaryOperatorType.Await, expression);
                        } else {
                            return UnaryOperatorResolveResult(SpecialType.UnknownType, UnaryOperatorType.Await, expression);
                        }
                    default:
                        throw new ArgumentException("Invalid value for UnaryOperatorType", "op");
                }
            }
            // If the type is nullable, get the underlying type:
            IType type = NullableType.GetUnderlyingType(expression.Type);
            bool isNullable = NullableType.IsNullable(expression.Type);

            // the operator is overloadable:
            OverloadResolution userDefinedOperatorOR = new OverloadResolution(compilation, new[] { expression }, conversions: conversions);
            foreach (var candidate in GetUserDefinedOperatorCandidates(type, overloadableOperatorName)) {
                userDefinedOperatorOR.AddCandidate(candidate);
            }
            if (userDefinedOperatorOR.FoundApplicableCandidate) {
                return CreateResolveResultForUserDefinedOperator(userDefinedOperatorOR);
            }

            expression = UnaryNumericPromotion(op, ref type, isNullable, expression);
            CSharpOperators.OperatorMethod[] methodGroup;
            CSharpOperators operators = CSharpOperators.Get(compilation);
            switch (op) {
                case UnaryOperatorType.Increment:
                case UnaryOperatorType.Decrement:
                case UnaryOperatorType.PostIncrement:
                case UnaryOperatorType.PostDecrement:
                    // C# 4.0 spec: §7.6.9 Postfix increment and decrement operators
                    // C# 4.0 spec: §7.7.5 Prefix increment and decrement operators
                    TypeCode code = ReflectionHelper.GetTypeCode(type);
                    if ((code >= TypeCode.SByte && code <= TypeCode.Decimal) || type.Kind == TypeKind.Enum || type.Kind == TypeKind.Pointer)
                        return UnaryOperatorResolveResult(expression.Type, op, expression);
                    else
                        return new ErrorResolveResult(expression.Type);
                case UnaryOperatorType.Plus:
                    methodGroup = operators.UnaryPlusOperators;
                    break;
                case UnaryOperatorType.Minus:
                    methodGroup = CheckForOverflow ? operators.CheckedUnaryMinusOperators : operators.UncheckedUnaryMinusOperators;
                    break;
                case UnaryOperatorType.Not:
                    methodGroup = operators.LogicalNegationOperators;
                    break;
                case UnaryOperatorType.BitNot:
                    if (type.Kind == TypeKind.Enum) {
                        if (expression.IsCompileTimeConstant && !isNullable) {
                            // evaluate as (E)(~(U)x);
                            var U = compilation.FindType(expression.ConstantValue.GetType());
                            var unpackedEnum = new ConstantResolveResult(U, expression.ConstantValue);
                            return CheckErrorAndResolveCast(expression.Type, ResolveUnaryOperator(op, unpackedEnum));
                        } else {
                            return UnaryOperatorResolveResult(expression.Type, op, expression);
                        }
                    } else {
                        methodGroup = operators.BitwiseComplementOperators;
                        break;
                    }
                default:
                    throw new InvalidOperationException();
            }
            OverloadResolution builtinOperatorOR = new OverloadResolution(compilation, new[] { expression }, conversions: conversions);
            foreach (var candidate in methodGroup) {
                builtinOperatorOR.AddCandidate(candidate);
            }
            CSharpOperators.UnaryOperatorMethod m = (CSharpOperators.UnaryOperatorMethod)builtinOperatorOR.BestCandidate;
            IType resultType = m.ReturnType;
            if (builtinOperatorOR.BestCandidateErrors != OverloadResolutionErrors.None) {
                // If there are any user-defined operators, prefer those over the built-in operators.
                // It'll be a more informative error.
                if (userDefinedOperatorOR.BestCandidate != null)
                    return CreateResolveResultForUserDefinedOperator(userDefinedOperatorOR);
                else
                    return new ErrorResolveResult(resultType);
            } else if (expression.IsCompileTimeConstant && m.CanEvaluateAtCompileTime) {
                object val;
                try {
                    val = m.Invoke(this, expression.ConstantValue);
                } catch (ArithmeticException) {
                    return new ErrorResolveResult(resultType);
                }
                return new ConstantResolveResult(resultType, val);
            } else {
                expression = Convert(expression, m.Parameters[0].Type, builtinOperatorOR.ArgumentConversions[0]);
                return UnaryOperatorResolveResult(resultType, op, expression);
            }
        }
Exemple #31
0
 /// <summary>
 /// Resolves an array creation.
 /// </summary>
 /// <param name="elementType">
 /// The array element type.
 /// Pass null to resolve an implicitly-typed array creation.
 /// </param>
 /// <param name="sizeArguments">
 /// The size arguments.
 /// The length of this array will be used as the number of dimensions of the array type.
 /// Negative values will be treated as errors.
 /// </param>
 /// <param name="initializerElements">
 /// The initializer elements. May be null if no array initializer was specified.
 /// The resolver may mutate this array to wrap elements in <see cref="ConversionResolveResult"/>s!
 /// </param>
 public ArrayCreateResolveResult ResolveArrayCreation(IType elementType, int[] sizeArguments, ResolveResult[] initializerElements = null)
 {
     ResolveResult[] sizeArgResults = new ResolveResult[sizeArguments.Length];
     for (int i = 0; i < sizeArguments.Length; i++) {
         if (sizeArguments[i] < 0)
             sizeArgResults[i] = ErrorResolveResult.UnknownError;
         else
             sizeArgResults[i] = new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), sizeArguments[i]);
     }
     return ResolveArrayCreation(elementType, sizeArgResults, initializerElements);
 }