private LocalILCodeVariable GenerateDictionaryEnumerateCode(Type type, string refName) { var extType = _il.TypeCache.Extend(type); var dictionaryMembers = new DictionaryMembers(extType); var local = _il.DeclareLocal("dictionary", dictionaryMembers.VariableType); _il.Construct(dictionaryMembers.Constructor); _il.Var.Set(local); NullableMembers keyNullableMembers; ILCodeParameter keyParam; var conditionLabel = _il.DefineLabel(); var bodyLabel = _il.DefineLabel(); var keyType = Members.Nullable.TryGetValue(dictionaryMembers.KeyType, out keyNullableMembers) ? keyNullableMembers.NullableType : dictionaryMembers.KeyType; var keyTypeExt = _il.TypeCache.Extend(keyType); // First of all, transfer to the condition part _il.TransferLong(conditionLabel); // Mark that we enter the body of the loop _il.MarkLabel(bodyLabel); if (keyTypeExt.IsValueOrNullableOfValue()) { keyParam = _il.DeclareLocal("ck", keyType); } else if (keyTypeExt.Class == TypeClass.Dictionary) { keyParam = GenerateDictionaryEnumerateCode(keyType, refName); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryInDictionaryKey); } else if (keyTypeExt.Class == TypeClass.Collection) { keyParam = GenerateCollectionContent(keyTypeExt, refName); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionInDictionaryKey); } else { var keyLocal = _il.DeclareLocal("ck", keyType); GenerateCreateAndChildCallCode(keyLocal); keyParam = keyLocal; _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryKey); } var throwExceptionLabel = _il.DefineLabel(); ILCodeParameter valueParam; NullableMembers valueNullableMembers; var hasNullableMembers = Members.Nullable.TryGetValue(dictionaryMembers.ValueType, out valueNullableMembers); var valueType = dictionaryMembers.ValueType; var extValueType = valueType.Extend(); if (extValueType.IsValueOrNullableOfValue()) { var loadTrueLabel = _il.DefineLabel(); var checkIfErrorLabel = _il.DefineLabel(); valueParam = _il.DeclareLocal("cv", hasNullableMembers ? valueNullableMembers.NullableType : dictionaryMembers.ValueType); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[dictionaryMembers.ValueType], Members.VisitArgsDictionaryValue, valueParam); _il.TransferLongIfFalse(loadTrueLabel); if (hasNullableMembers) { _il.Snippets.InvokeMethod(valueParam, valueNullableMembers.GetHasValue); _il.Negate(); } else { _il.Snippets.AreEqual(valueParam, null); } _il.TransferLong(checkIfErrorLabel); _il.MarkLabel(loadTrueLabel); _il.LoadValue(true); _il.MarkLabel(checkIfErrorLabel); _il.TransferLongIfTrue(throwExceptionLabel); } else if (extValueType.Class == TypeClass.Dictionary) { var callTryVisitValue = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryInDictionaryValue); _il.Snippets.AreEqual(callTryVisitValue, (int)ValueState.Found); _il.TransferLongIfFalse(throwExceptionLabel); valueParam = GenerateDictionaryEnumerateCode(valueType, refName); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryInDictionaryValue); } else if (extValueType.Class == TypeClass.Collection) { var callTryVisit = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionInDictionaryValue); _il.Snippets.AreEqual(callTryVisit, (int)ValueState.Found); _il.TransferLongIfFalse(throwExceptionLabel); valueParam = GenerateCollectionContent(_il.TypeCache.Extend(valueType), refName); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionInDictionaryValue); } else { var callTryVisit = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryValue); _il.Snippets.AreEqual(callTryVisit, (int)ValueState.Found); _il.TransferLongIfFalse(throwExceptionLabel); var valueLocal = _il.DeclareLocal("cv", hasNullableMembers ? valueNullableMembers.NullableType : dictionaryMembers.ValueType); GenerateCreateAndChildCallCode(valueLocal); valueParam = valueLocal; _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryValue); } _il.Var.Load(local); GenerateLoadParamValueCode(keyParam); GenerateLoadParamValueCode(valueParam); _il.CallVirt(dictionaryMembers.Add); _il.TransferLong(conditionLabel); _il.MarkLabel(throwExceptionLabel); _il.Snippets.Throw(new CallMethodILCode(Members.ExceptionNoDictionaryValue, refName)); _il.MarkLabel(conditionLabel); if (keyTypeExt.IsValueOrNullableOfValue()) { var loadZeroLabel = _il.DefineLabel(); var checkConditionLabel = _il.DefineLabel(); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[keyType], Members.VisitArgsDictionaryKey, keyParam); _il.TransferLongIfFalse(loadZeroLabel); if (keyType.IsValueType) { _il.Snippets.InvokeMethod(keyParam, Members.Nullable[keyType].GetHasValue); _il.TransferLong(checkConditionLabel); } else { _il.Snippets.AreEqual(keyParam, ILCodeParameter.Null); _il.Negate(); _il.TransferLong(checkConditionLabel); } _il.MarkLabel(loadZeroLabel); _il.LoadValue(false); _il.MarkLabel(checkConditionLabel); _il.TransferLongIfTrue(bodyLabel); } else if (keyTypeExt.Class == TypeClass.Dictionary) { var callTryVisitKey = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryInDictionaryKey); _il.Snippets.AreEqual(callTryVisitKey, (int)ValueState.Found); _il.TransferLongIfTrue(bodyLabel); } else if (keyTypeExt.Class == TypeClass.Collection) { var callTryVisitKey = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionInDictionaryKey); _il.Snippets.AreEqual(callTryVisitKey, (int)ValueState.Found); _il.TransferLongIfTrue(bodyLabel); } else { var callTryVisit = new CallMethodILCode(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryKey); _il.Snippets.AreEqual(callTryVisit, (int)ValueState.Found); _il.TransferLongIfTrue(bodyLabel); } return local; }
private ILLocalVariable GenerateDictionaryEnumerateCode(Type type, string refName) { var extType = _typeProvider.Extend(type); var dictionaryMembers = new DictionaryMembers(extType); var local = _il.NewLocal(dictionaryMembers.VariableType); _il.Construct(dictionaryMembers.Constructor); _il.Set(local); var keyType = Members.Nullable.TryGetValue(dictionaryMembers.KeyType, out var keyNullableMembers) ? keyNullableMembers.NullableType : dictionaryMembers.KeyType; var conditionLabel = _il.NewLabel(); var bodyLabel = _il.NewLabel(); var keyTypeExt = _typeProvider.Extend(keyType); // First of all, transfer to the condition part conditionLabel.TransferLong(); // Mark that we enter the body of the loop bodyLabel.Mark(); ILPointer keyParam; if (keyTypeExt.IsValueOrNullableOfValue()) { keyParam = _il.NewLocal(keyType); } else if (keyTypeExt.Classification == TypeClassification.Dictionary) { keyParam = GenerateDictionaryEnumerateCode(keyType, refName); _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryInDictionaryKey); } else if (keyTypeExt.Classification == TypeClassification.Collection) { keyParam = GenerateCollectionContent(keyTypeExt, refName); _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionInDictionaryKey); } else { var keyLocal = _il.NewLocal(keyType); GenerateCreateAndChildCallCode(keyLocal); keyParam = keyLocal; _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryKey); } var throwExceptionLabel = _il.NewLabel(); var hasNullableMembers = Members.Nullable.TryGetValue( dictionaryMembers.ValueType, out var valueNullableMembers); var valueType = dictionaryMembers.ValueType; var extValueType = _typeProvider.Extend(valueType); ILPointer valueParam; if (extValueType.IsValueOrNullableOfValue()) { var loadTrueLabel = _il.NewLabel(); var checkIfErrorLabel = _il.NewLabel(); valueParam = _il.NewLocal(hasNullableMembers ? valueNullableMembers.NullableType : dictionaryMembers.ValueType); _il.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[dictionaryMembers.ValueType], Members.VisitArgsDictionaryValue, valueParam); loadTrueLabel.TransferLongIfFalse(); if (hasNullableMembers) { _il.InvokeMethod(valueParam, valueNullableMembers.GetHasValue); _il.Negate(); } else { _il.AreEqual(valueParam, null); } checkIfErrorLabel.TransferLong(); loadTrueLabel.Mark(); _il.Load(true); checkIfErrorLabel.Mark(); throwExceptionLabel.TransferLongIfTrue(); } else if (extValueType.Classification == TypeClassification.Dictionary) { var callTryVisitValue = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryInDictionaryValue); _il.AreEqual(callTryVisitValue, (int)ValueState.Found); throwExceptionLabel.TransferLongIfFalse(); valueParam = GenerateDictionaryEnumerateCode(valueType, refName); _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryInDictionaryValue); } else if (extValueType.Classification == TypeClassification.Collection) { var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionInDictionaryValue); _il.AreEqual(callTryVisit, (int)ValueState.Found); throwExceptionLabel.TransferLongIfFalse(); valueParam = GenerateCollectionContent(_typeProvider.Extend(valueType), refName); _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionInDictionaryValue); } else { var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryValue); _il.AreEqual(callTryVisit, (int)ValueState.Found); throwExceptionLabel.TransferLongIfFalse(); var valueLocal = _il.NewLocal(hasNullableMembers ? valueNullableMembers.NullableType : dictionaryMembers.ValueType); GenerateCreateAndChildCallCode(valueLocal); valueParam = valueLocal; _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryValue); } _il.Load(local); GenerateLoadParamValueCode(keyParam); GenerateLoadParamValueCode(valueParam); _il.EmitCall(OpCodes.Callvirt, dictionaryMembers.Add, null); conditionLabel.TransferLong(); throwExceptionLabel.Mark(); _il.Throw(new ILCallMethodSnippet(Members.ExceptionNoDictionaryValue, refName)); conditionLabel.Mark(); if (keyTypeExt.IsValueOrNullableOfValue()) { var loadZeroLabel = _il.NewLabel(); var checkConditionLabel = _il.NewLabel(); _il.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[keyType], Members.VisitArgsDictionaryKey, keyParam); loadZeroLabel.TransferLongIfFalse(); if (keyTypeExt.Info.IsValueType) { _il.InvokeMethod(keyParam, Members.Nullable[keyType].GetHasValue); checkConditionLabel.TransferLong(); } else { _il.AreEqual(keyParam, ILPointer.Null); _il.Negate(); checkConditionLabel.TransferLong(); } loadZeroLabel.Mark(); _il.Load(false); checkConditionLabel.Mark(); bodyLabel.TransferLongIfTrue(); } else if (keyTypeExt.Classification == TypeClassification.Dictionary) { var callTryVisitKey = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryInDictionaryKey); _il.AreEqual(callTryVisitKey, (int)ValueState.Found); bodyLabel.TransferLongIfTrue(); } else if (keyTypeExt.Classification == TypeClassification.Collection) { var callTryVisitKey = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionInDictionaryKey); _il.AreEqual(callTryVisitKey, (int)ValueState.Found); bodyLabel.TransferLongIfTrue(); } else { var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryKey); _il.AreEqual(callTryVisit, (int)ValueState.Found); bodyLabel.TransferLongIfTrue(); } return(local); }