private ILCodeParameter GenerateCollectionContent(ExtendedType target, string refName)
        {
            var collectionMembers = new CollectionMembers(target);
            var isValueType = collectionMembers.ElementType.IsValueType;

            var collectionLocal = _il.DeclareLocal("collection", collectionMembers.VariableType);
            _il.Construct(collectionMembers.Constructor);
            _il.Cast(collectionMembers.VariableType);
            _il.Var.Set(collectionLocal);

            var valueLocal = DeclareCollectionItemLocal("cv", collectionMembers.ElementType); ;

            if (collectionMembers.ElementTypeExt.IsValueOrNullableOfValue()) {
                _il.Snippets.WhileLoop(il => { // While condition
                    _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[collectionMembers.ElementType], Members.VisitArgsCollectionItem, valueLocal);

                    var valueNotFoundLabel = _il.DefineLabel();
                    _il.TransferLongIfFalse(valueNotFoundLabel);

                    if (isValueType) {
                        _il.Snippets.InvokeMethod(valueLocal, Members.Nullable[collectionMembers.ElementType].GetHasValue);
                    }
                    else {
                        _il.Snippets.AreEqual(valueLocal, ILCodeParameter.Null);
                        _il.Negate();
                    }

                    var isNullLabel = _il.DefineLabel();
                    _il.TransferLong(isNullLabel);

                    _il.MarkLabel(valueNotFoundLabel);
                    _il.LoadValue(0);
                    _il.MarkLabel(isNullLabel);
                }, il => {
                    _il.Var.Load(collectionLocal);

                    GenerateLoadParamValueCode(valueLocal);

                    _il.CallVirt(collectionMembers.Add);
                });
            }
            else if (collectionMembers.ElementTypeExt.Class == TypeClass.Dictionary) {
                _il.Snippets.WhileLoop(il => { // Condition
                    var callTryVisit = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryInCollection);
                    _il.Snippets.AreEqual(callTryVisit, (int)ValueState.Found);
                }, il => {
                    var contentParam = GenerateDictionaryEnumerateCode(collectionMembers.ElementType, refName);
                    _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryInCollection);
                    _il.Snippets.InvokeMethod(collectionLocal, collectionMembers.Add, contentParam);
                });
            }
            else if (collectionMembers.ElementTypeExt.Class == TypeClass.Collection) {
                _il.Snippets.WhileLoop(il => { // Condition
                    var callTryVisit = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionInCollection);
                    _il.Snippets.AreEqual(callTryVisit, (int)ValueState.Found);
                }, il => {
                    var contentParam = GenerateCollectionContent(collectionMembers.ElementTypeExt, refName);
                    _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionInCollection);
                    _il.Snippets.InvokeMethod(collectionLocal, collectionMembers.Add, contentParam);
                });
            }
            else {
                _il.Snippets.WhileLoop(il => {
                    var callTryVisit = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionItem);
                    _il.Snippets.AreEqual(callTryVisit, (int)ValueState.Found);
                }, il => {
                    GenerateCreateAndChildCallCode(valueLocal);
                    _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionItem);
                    _il.Snippets.InvokeMethod(collectionLocal, collectionMembers.Add, valueLocal);
                });
            }
            if (target.Ref.IsArray)
                return new CallMethodILCode(collectionMembers.ToArray, collectionLocal);

            return collectionLocal;
        }
Ejemplo n.º 2
0
        private ILPointer GenerateCollectionContent(ExtendedType target, string refName)
        {
            var collectionMembers = new CollectionMembers(target);
            var isValueType       = collectionMembers.ElementType.GetTypeInfo().IsValueType;

            var collectionLocal = _il.NewLocal(collectionMembers.VariableType);
            var collection      = ILPointer.New(collectionMembers.Constructor)
                                  .Cast(collectionMembers.VariableType);

            _il.Set(collectionLocal, collection);

            var valueLocal = DeclareCollectionItemLocal(collectionMembers.ElementType);;

            if (collectionMembers.ElementTypeExt.IsValueOrNullableOfValue())
            {
                _il.WhileLoop(il => { // While condition
                    _il.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[collectionMembers.ElementType], Members.VisitArgsCollectionItem, valueLocal);

                    var valueNotFoundLabel = _il.NewLabel();
                    valueNotFoundLabel.TransferLongIfFalse();

                    if (isValueType)
                    {
                        _il.InvokeMethod(valueLocal, Members.Nullable[collectionMembers.ElementType].GetHasValue);
                    }
                    else
                    {
                        _il.AreEqual(valueLocal, ILPointer.Null);
                        _il.Negate();
                    }

                    var isNullLabel = _il.NewLabel();
                    isNullLabel.TransferLong();

                    valueNotFoundLabel.Mark();
                    _il.Load(0);
                    isNullLabel.Mark();
                }, il => {
                    _il.Load(collectionLocal);

                    GenerateLoadParamValueCode(valueLocal);

                    _il.EmitCall(OpCodes.Callvirt, collectionMembers.Add, null);
                });
            }
            else if (collectionMembers.ElementTypeExt.Classification == TypeClassification.Dictionary)
            {
                _il.WhileLoop(il => { // Condition
                    var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryInCollection);
                    _il.AreEqual(callTryVisit, (int)ValueState.Found);
                }, il => {
                    var contentParam = GenerateDictionaryEnumerateCode(collectionMembers.ElementType, refName);
                    _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryInCollection);
                    _il.InvokeMethod(collectionLocal, collectionMembers.Add, contentParam);
                });
            }
            else if (collectionMembers.ElementTypeExt.Classification == TypeClassification.Collection)
            {
                _il.WhileLoop(il => { // Condition
                    var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionInCollection);
                    _il.AreEqual(callTryVisit, (int)ValueState.Found);
                }, il => {
                    var contentParam = GenerateCollectionContent(collectionMembers.ElementTypeExt, refName);
                    _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionInCollection);
                    _il.InvokeMethod(collectionLocal, collectionMembers.Add, contentParam);
                });
            }
            else
            {
                _il.WhileLoop(il => {
                    var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionItem);
                    _il.AreEqual(callTryVisit, (int)ValueState.Found);
                }, il => {
                    GenerateCreateAndChildCallCode(valueLocal);
                    _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionItem);
                    _il.InvokeMethod(collectionLocal, collectionMembers.Add, valueLocal);
                });
            }
            if (target.Ref.IsArray)
            {
                return(new ILCallMethodSnippet(collectionMembers.ToArray, collectionLocal));
            }

            return(collectionLocal);
        }