Exemplo n.º 1
0
 public TranslatedExpression Build(CallInstruction inst)
 {
     if (inst is NewObj newobj && IL.Transforms.DelegateConstruction.IsDelegateConstruction(newobj, true))
     {
         return(HandleDelegateConstruction(newobj));
     }
     if (settings.TupleTypes && TupleTransform.MatchTupleConstruction(inst as NewObj, out var tupleElements) && tupleElements.Length >= 2)
     {
         var elementTypes = TupleType.GetTupleElementTypes(inst.Method.DeclaringType);
         Debug.Assert(!elementTypes.IsDefault, "MatchTupleConstruction should not success unless we got a valid tuple type.");
         Debug.Assert(elementTypes.Length == tupleElements.Length);
         var tuple      = new TupleExpression();
         var elementRRs = new List <ResolveResult>();
         foreach (var(element, elementType) in tupleElements.Zip(elementTypes))
         {
             var translatedElement = expressionBuilder.Translate(element, elementType)
                                     .ConvertTo(elementType, expressionBuilder, allowImplicitConversion: true);
             tuple.Elements.Add(translatedElement.Expression);
             elementRRs.Add(translatedElement.ResolveResult);
         }
         return(tuple.WithRR(new TupleResolveResult(
                                 expressionBuilder.compilation,
                                 elementRRs.ToImmutableArray()
                                 )).WithILInstruction(inst));
     }
     return(Build(inst.OpCode, inst.Method, inst.Arguments, inst.ConstrainedTo).WithILInstruction(inst));
 }
Exemplo n.º 2
0
 /// <summary>
 /// Get index of deconstruction result or tuple element
 /// Returns -1 on failure.
 /// </summary>
 int FindIndex(ILInstruction inst, out Action <DeconstructInstruction> delayedActions)
 {
     delayedActions = null;
     if (inst.MatchLdLoc(out var v))
     {
         if (!deconstructionResultsLookup.TryGetValue(v, out int index))
         {
             return(-1);
         }
         return(index);
     }
     if (inst.MatchLdFld(out _, out _))
     {
         if (!TupleTransform.MatchTupleFieldAccess((LdFlda)((LdObj)inst).Target, out var tupleType, out var target, out int index))
         {
             return(-1);
         }
         // Item fields are one-based, we use zero-based indexing.
         index--;
         // normalize tuple type
         tupleType = TupleType.FromUnderlyingType(context.TypeSystem, tupleType);
         if (!target.MatchLdLoca(out v))
         {
             return(-1);
         }
         if (this.tupleVariable == null)
         {
             this.tupleVariable         = v;
             this.tupleType             = (TupleType)tupleType;
             this.deconstructionResults = new ILVariable[this.tupleType.Cardinality];
         }
         if (this.tupleType.Cardinality < 2)
         {
             return(-1);
         }
         if (v != tupleVariable || !this.tupleType.Equals(tupleType))
         {
             return(-1);
         }
         if (this.deconstructionResults[index] == null)
         {
             var freshVar = new ILVariable(VariableKind.StackSlot, this.tupleType.ElementTypes[index])
             {
                 Name = "E_" + index
             };
             delayedActions += _ => context.Function.Variables.Add(freshVar);
             this.deconstructionResults[index] = freshVar;
         }
         delayedActions += _ => {
             inst.ReplaceWith(new LdLoc(this.deconstructionResults[index]));
         };
         return(index);
     }
     return(-1);
 }