public ShuffleTemplate( string className, Type outerKeyType, Type sourceType, Type innerKeyType, string inlinedHashCodeComputation, bool nested, bool powerOf2) : base(className) { Contract.Requires(className != null); Contract.Requires(outerKeyType != null); Contract.Requires(sourceType != null); Contract.Requires(innerKeyType != null); this.inlinedHashCodeComputation = inlinedHashCodeComputation; this.isFirstLevelGroup = !nested; this.powerOf2 = powerOf2; var tm = new TypeMapper(outerKeyType, sourceType, innerKeyType); this.TOuterKey = tm.CSharpNameFor(outerKeyType); this.TSource = tm.CSharpNameFor(sourceType); this.TInnerKey = tm.CSharpNameFor(innerKeyType); this.genericParameters = tm.GenericTypeVariables(outerKeyType, sourceType, innerKeyType).BracketedCommaSeparatedString(); this.resultBatchClassType = this.isFirstLevelGroup ? Transformer.GetBatchClassName(innerKeyType, sourceType) : Transformer.GetBatchClassName(typeof(CompoundGroupKey <,>).MakeGenericType(outerKeyType, innerKeyType), sourceType); this.resultBatchGenericParameters = this.genericParameters; this.sourceBatchClassType = Transformer.GetBatchClassName(outerKeyType, sourceType); this.TOuterKeyTSourceGenericParameters = tm.GenericTypeVariables(outerKeyType, sourceType).BracketedCommaSeparatedString(); }
protected CommonUnaryTemplate(string className, Type keyType, Type payloadType, Type resultType, bool suppressPayloadBatch = false) : base(className) { this.keyType = keyType; this.payloadType = payloadType; this.resultType = resultType; var tm = new TypeMapper(keyType, payloadType, resultType); this.TKey = tm.CSharpNameFor(keyType); this.TPayload = tm.CSharpNameFor(payloadType); this.TResult = tm.CSharpNameFor(resultType); if (!suppressPayloadBatch) { this.TKeyTPayloadGenericParameters = tm.GenericTypeVariables(keyType, payloadType).BracketedCommaSeparatedString(); this.BatchGeneratedFrom_TKey_TPayload = Transformer.GetBatchClassName(keyType, payloadType); } this.payloadRepresentation = new ColumnarRepresentation(payloadType); this.fields = this.payloadRepresentation.AllFields; this.noFields = this.payloadRepresentation.noFields; this.resultRepresentation = new ColumnarRepresentation(resultType); }
private TemporalEgressTemplate(Type tKey, Type tPayload, Type tResult, string partitionString, string ingressType, bool isColumnar) : base($"GeneratedTemporalEgress_{TemporalEgressSequenceNumber++}") { var tm = new TypeMapper(tKey, tPayload, tResult); this.payloadRepresentation = new ColumnarRepresentation(tPayload); this.BatchGeneratedFrom_TKey_TPayload = Transformer.GetBatchClassName( tKey == typeof(Empty) ? tKey : typeof(PartitionKey <>).MakeGenericType(tKey), tPayload); this.TKeyTPayloadGenericParameters = tm.GenericTypeVariables(tKey, tPayload).BracketedCommaSeparatedString(); this.fields = this.payloadRepresentation.AllFields; this.TKey = tm.CSharpNameFor(tKey); this.TPayload = tm.CSharpNameFor(tPayload); this.TResult = tm.CSharpNameFor(tResult); this.partitionString = partitionString; this.ingressType = ingressType; this.partitionKeyArgument = !string.IsNullOrEmpty(partitionString) ? "colkey[i].Key, " : string.Empty; this.genericArguments = string.IsNullOrEmpty(partitionString) ? this.TPayload : this.TKey + ", " + this.TPayload; this.egress = (ingressType != "StreamEvent") ? this.TResult : partitionString + "StreamEvent<" + this.genericArguments + ">"; this.inputKey = string.IsNullOrEmpty(partitionString) ? this.TKey : "PartitionKey<" + this.TKey + ">"; this.isColumnar = isColumnar; }
private UngroupTemplate( string className, bool ungroupingFromCompound, Type outerKeyType, Type innerKeyType, Type innerResultType, Type resultType) { Contract.Requires(className != null); Contract.Requires(outerKeyType != null); Contract.Requires(innerKeyType != null); Contract.Requires(innerResultType != null); Contract.Requires(resultType != null); this.CLASSNAME = className; this.outerKeyType = outerKeyType; this.innerKeyType = innerKeyType; this.innerResultType = innerResultType; this.resultType = resultType; this.ungroupingToUnit = outerKeyType == typeof(Empty); this.ungroupingFromCompound = ungroupingFromCompound; var tm = new TypeMapper(outerKeyType, innerKeyType, innerResultType, resultType); this.TOuterKey = tm.CSharpNameFor(outerKeyType); this.TInnerKey = tm.CSharpNameFor(innerKeyType); this.TInnerResult = tm.CSharpNameFor(innerResultType); this.TResult = tm.CSharpNameFor(resultType); var gps = tm.GenericTypeVariables(outerKeyType, innerKeyType, innerResultType, resultType); this.genericParameters = gps.BracketedCommaSeparatedString(); this.numberOfGenericParameters = gps.Count(); this.inputBatchClassType = ungroupingFromCompound ? Transformer.GetBatchClassName(typeof(CompoundGroupKey <,>).MakeGenericType(outerKeyType, innerKeyType), innerResultType) : Transformer.GetBatchClassName(innerKeyType, innerResultType); this.inputBatchGenericParameters = ungroupingFromCompound ? tm.GenericTypeVariables(outerKeyType, innerKeyType, innerResultType).BracketedCommaSeparatedString() : tm.GenericTypeVariables(innerKeyType, innerResultType).BracketedCommaSeparatedString(); this.resultBatchClassType = Transformer.GetBatchClassName(outerKeyType, resultType); this.resultBatchGenericParameters = tm.GenericTypeVariables(outerKeyType, resultType).BracketedCommaSeparatedString(); }
public static Tuple <Type, string> Generate <TKey, TPayload, TResult>(SelectManyStreamable <TKey, TPayload, TResult> stream) { Contract.Ensures(Contract.Result <Tuple <Type, string> >() == null || typeof(UnaryPipe <TKey, TPayload, TResult>).GetTypeInfo().IsAssignableFrom(Contract.Result <Tuple <Type, string> >().Item1)); string generatedClassName; string expandedCode; string errorMessages = null; try { generatedClassName = $"SelectMany_{sequenceNumber++}"; var keyType = typeof(TKey); var payloadType = typeof(TPayload); var resultType = typeof(TResult); var template = new SelectManyTemplate(generatedClassName, keyType, payloadType, resultType); var tm = new TypeMapper(keyType, payloadType, resultType); var gps = tm.GenericTypeVariables(keyType, payloadType, resultType); template.genericParameters = gps.BracketedCommaSeparatedString(); template.numberOfGenericParameters = gps.Count(); template.TKeyTResultGenericParameters = tm.GenericTypeVariables(keyType, resultType).BracketedCommaSeparatedString(); template.MemoryPoolGenericParameters = $"<{template.TKey}, {template.TResult}>"; if (resultType == typeof(int) || resultType == typeof(long) || resultType == typeof(string)) { template.MemoryPoolGenericParameters = string.Empty; } var payloadParameterIndex = 0; if (stream.HasKey && stream.HasStartEdge) { payloadParameterIndex = 2; } else if (stream.HasKey || stream.HasStartEdge) { payloadParameterIndex = 1; } var selector = stream.Selector; var payloadParameter = selector.Parameters.ElementAt(payloadParameterIndex); template.PARAMETER = payloadParameter.Name; template.resultPayloadRepresentation = new ColumnarRepresentation(resultType); template.resultFields = template.resultPayloadRepresentation.AllFields; if (template.numberOfGenericParameters > 0) { generatedClassName = generatedClassName + "`" + template.numberOfGenericParameters.ToString(CultureInfo.InvariantCulture); } expandedCode = string.Empty; Expression transformedSelector = selector; // No substitutions are made for the start edge parameter or key parameter. Both just remain in the // body of the result selector and are set as local variables in the generated code. var keyParameterIndex = stream.HasStartEdge ? 1 : 0; var tuple = OptimizeSelectMany(selector.Body); if (tuple != null) { template.enumerableRepeatSelector = true; var resultSelector = stream.Selector; var sourceMessageType = StreamMessageManager.GetStreamMessageType <TKey, TPayload>(); var pseudoLambdaParameters = new ParameterExpression[stream.HasKey ? 2 : 1]; var pseudoLambdaIndex = 0; if (stream.HasKey) { pseudoLambdaParameters[pseudoLambdaIndex++] = selector.Parameters[keyParameterIndex]; } pseudoLambdaParameters[pseudoLambdaIndex] = payloadParameter; var pseudoLambda = Expression.Lambda(tuple.Item1, pseudoLambdaParameters); var parameterSubstitutions = new List <Tuple <ParameterExpression, SelectParameterInformation> > { Tuple.Create(payloadParameter, new SelectParameterInformation() { BatchName = "batch", BatchType = sourceMessageType, IndexVariableName = "i", parameterRepresentation = new ColumnarRepresentation(payloadType) }) }; var projectionResult = SelectTransformer.Transform(pseudoLambda, parameterSubstitutions, template.resultPayloadRepresentation, true, stream.HasStartEdge); template.computedFields = projectionResult.ComputedFields; template.useEnumerator = false; var loopCounter = tuple.Item2; var newParameters = new ParameterExpression[stream.HasKey ? 2 : 1]; newParameters[0] = payloadParameter; if (stream.HasKey) { newParameters[1] = selector.Parameters[keyParameterIndex]; } var loopCounterLambda = Expression.Lambda(loopCounter, payloadParameter); var transformedLoopCounter = Extensions.TransformFunction <TKey, TPayload>(loopCounterLambda, 0); template.loopCounter = transformedLoopCounter.Body.ExpressionToCSharp(); // REVIEW: Alternative: use Inline to replace occurrences of the key parameter // with "batch.key.col[i]". if (stream.HasKey) { template.keyParameterName = selector.Parameters[keyParameterIndex].Name; } } else { transformedSelector = Extensions.TransformFunction <TKey, TPayload>(stream.Selector, payloadParameterIndex).Body; if (transformedSelector == null) { template.useEnumerator = true; template.transformedSelectorAsSource = stream.Selector.ExpressionToCSharp(); } else { var tuple2 = OptimizeSelectMany(transformedSelector); if (tuple2 != null) { template.useEnumerator = false; template.loopCounter = tuple2.Item2.ExpressionToCSharp(); template.transformedSelectorAsSource = tuple2.Item1.ExpressionToCSharp(); } else { template.useEnumerator = true; template.transformedSelectorAsSource = transformedSelector.ExpressionToCSharp(); } } } template.StartEdgeParameterName = stream.HasStartEdge ? selector.Parameters.ElementAt(0).Name : null; template.hasKey = stream.HasKey; expandedCode = template.TransformText(); var assemblyReferences = Transformer.AssemblyReferencesNeededFor(typeof(TKey), typeof(TPayload), typeof(TResult)); assemblyReferences.Add(typeof(IStreamable <,>).GetTypeInfo().Assembly); assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TPayload>()); assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TResult>()); assemblyReferences.Add(Transformer.GeneratedMemoryPoolAssembly <TKey, TResult>()); assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(stream.Selector)); var a = Transformer.CompileSourceCode(expandedCode, assemblyReferences, out errorMessages); var t = a.GetType(generatedClassName); t = t.InstantiateAsNecessary(typeof(TKey), typeof(TPayload), typeof(TResult)); return(Tuple.Create(t, errorMessages)); } catch { if (Config.CodegenOptions.DontFallBackToRowBasedExecution) { throw new InvalidOperationException("Code Generation failed when it wasn't supposed to!"); } return(Tuple.Create((Type)null, errorMessages)); } }
/// <summary> /// Generate a batch class definition to be used as a Union pipe. /// Compile the definition, dynamically load the assembly containing it, and return the Type representing the /// union pipe class. /// </summary> /// <typeparam name="TKey">The key type for both sides.</typeparam> /// <typeparam name="TPayload">The payload type.</typeparam> /// <returns> /// A type that is defined to be a subtype of BinaryPipe<<typeparamref name="TKey"/>,<typeparamref name="TPayload"/>, <typeparamref name="TPayload"/>, <typeparamref name="TKey"/>, <typeparamref name="TPayload"/>>. /// </returns> internal static Tuple <Type, string> GenerateUnionPipeClass <TKey, TPayload>( UnionStreamable <TKey, TPayload> stream) { Contract.Requires(stream != null); Contract.Ensures(Contract.Result <Tuple <Type, string> >() == null || typeof(BinaryPipe <TKey, TPayload, TPayload, TPayload>).GetTypeInfo().IsAssignableFrom(Contract.Result <Tuple <Type, string> >().Item1)); #if CODEGEN_TIMING Stopwatch sw = new Stopwatch(); sw.Start(); #endif string errorMessages = null; try { var template = new UnionTemplate(); var keyType = template.keyType = typeof(TKey); var payloadType = template.payloadType = typeof(TPayload); var tm = new TypeMapper(keyType, payloadType); template.TKey = tm.CSharpNameFor(keyType); template.TPayload = tm.CSharpNameFor(payloadType); var gps = tm.GenericTypeVariables(keyType, payloadType); template.genericParameters = gps.BracketedCommaSeparatedString(); template.className = string.Format("GeneratedUnion_{0}", UnionSequenceNumber++); var resultRepresentation = new ColumnarRepresentation(payloadType); var batchGeneratedFrom_TKey_TPayload = Transformer.GetBatchClassName(keyType, payloadType); var keyAndPayloadGenericParameters = tm.GenericTypeVariables(keyType, payloadType).BracketedCommaSeparatedString(); template.GeneratedBatchName = batchGeneratedFrom_TKey_TPayload + keyAndPayloadGenericParameters; template.fields = resultRepresentation.AllFields; template.staticCtor = Transformer.StaticCtor(template.className); var expandedCode = template.TransformText(); var assemblyReferences = Transformer.AssemblyReferencesNeededFor(typeof(TKey), typeof(TPayload)); assemblyReferences.Add(typeof(IStreamable <,>).GetTypeInfo().Assembly); assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TPayload>()); var a = Transformer.CompileSourceCode(expandedCode, assemblyReferences, out errorMessages); var realClassName = template.className.AddNumberOfNecessaryGenericArguments(keyType, payloadType); var t = a.GetType(realClassName); if (t.GetTypeInfo().IsGenericType) { var list = keyType.GetAnonymousTypes(); list.AddRange(payloadType.GetAnonymousTypes()); return(Tuple.Create(t.MakeGenericType(list.ToArray()), errorMessages)); } else { return(Tuple.Create(t, errorMessages)); } } catch { if (Config.CodegenOptions.DontFallBackToRowBasedExecution) { throw new InvalidOperationException("Code Generation failed when it wasn't supposed to!"); } return(Tuple.Create((Type)null, errorMessages)); } }
public static Tuple <Type, string> Generate <TKey, TPayload, TResult>(SelectStreamable <TKey, TPayload, TResult> stream) { Contract.Ensures(Contract.Result <Tuple <Type, string> >() == null || typeof(UnaryPipe <TKey, TPayload, TResult>).GetTypeInfo().IsAssignableFrom(Contract.Result <Tuple <Type, string> >().Item1)); string generatedClassName; string errorMessages = null; try { var keyType = typeof(TKey); var payloadType = typeof(TPayload); var resultType = typeof(TResult); generatedClassName = string.Format("Select_{0}_{1}_{2}_{3}", keyType.GetValidIdentifier(), payloadType.GetValidIdentifier(), resultType.GetValidIdentifier(), sequenceNumber++); var template = new SelectTemplate(generatedClassName, keyType, payloadType, resultType); var tm = new TypeMapper(keyType, payloadType, resultType); var gps = tm.GenericTypeVariables(keyType, payloadType, resultType); template.genericParameters = gps.BracketedCommaSeparatedString(); template.numberOfGenericParameters = gps.Count(); template.TKeyTResultGenericParameters = tm.GenericTypeVariables(keyType, resultType).BracketedCommaSeparatedString(); template.MemoryPoolGenericParameters = $"<{template.TKey}, {template.TResult}>"; if (resultType == typeof(int) || resultType == typeof(long) || resultType == typeof(string)) { template.MemoryPoolGenericParameters = string.Empty; } var payloadParameterIndex = 0; if (stream.HasKey && stream.HasStartEdge) { payloadParameterIndex = 2; } else if (stream.HasKey || stream.HasStartEdge) { payloadParameterIndex = 1; } template.PARAMETER = stream.Selector.Parameters[payloadParameterIndex].Name; template.resultPayloadRepresentation = new ColumnarRepresentation(resultType); template.destinationFields = template.resultPayloadRepresentation.AllFields; if (template.numberOfGenericParameters > 0) { generatedClassName = generatedClassName + "`" + template.numberOfGenericParameters.ToString(CultureInfo.InvariantCulture); } var resultSelector = stream.Selector; var sourceMessageType = StreamMessageManager.GetStreamMessageType <TKey, TPayload>(); var parameterSubsitutions = new List <Tuple <ParameterExpression, SelectParameterInformation> >(); // Don't create a parameter substitution for the start edge parameter. That will just remain in the // body of the result selector and will be set as a local variable in the generated code. if (stream.HasKey) { var keyRepresentation = new ColumnarRepresentation(keyType, "key"); var keyParameterIndex = stream.HasStartEdge ? 1 : 0; parameterSubsitutions.Add(Tuple.Create( resultSelector.Parameters.ElementAt(keyParameterIndex), new SelectParameterInformation() { BatchName = "sourceBatch", BatchType = sourceMessageType, IndexVariableName = "i", parameterRepresentation = keyRepresentation, })); } parameterSubsitutions.Add(Tuple.Create( resultSelector.Parameters.ElementAt(payloadParameterIndex), new SelectParameterInformation() { BatchName = "sourceBatch", BatchType = sourceMessageType, IndexVariableName = "i", parameterRepresentation = new ColumnarRepresentation(payloadType) })); var projectionResult = SelectTransformer.Transform(resultSelector, parameterSubsitutions, template.resultPayloadRepresentation, false, stream.HasStartEdge); if (projectionResult.Error) { if (Config.CodegenOptions.SuperStrictColumnar) { throw new InvalidOperationException("Code Generation couldn't transform a selector!"); } return(Tuple.Create((Type)null, errorMessages)); } template.StartEdgeParameterName = stream.HasStartEdge ? resultSelector.Parameters.ElementAt(0).Name : null; template.computedFields = projectionResult.ComputedFields; template.swingingFields = projectionResult.SwingingFields; template.unassignedFields = projectionResult.UnmentionedFields; template.ProjectionReturningResultInstance = projectionResult.ProjectionReturningResultInstance; template.multiStringOperations = projectionResult.MultiStringOperations; template.needSourceInstance = projectionResult.NeedsSourceInstance; var d = new Dictionary <MyFieldInfo, int>(); foreach (var f in template.swingingFields) { var target = f.Item1; var source = f.Item2; if (!d.ContainsKey(source)) { d.Add(source, 0); } d[source] = d[source] + 1; } template.swungFieldsCount = d; template.nonSwingingFields = template.fields.Where(sf => !template.swingingFields.Any(swingingField => swingingField.Item2.Equals(sf))); var expandedCode = template.TransformText(); var assemblyReferences = Transformer.AssemblyReferencesNeededFor( typeof(TKey), typeof(TPayload), typeof(TResult), typeof(IStreamable <,>)); assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TPayload>()); assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TResult>()); assemblyReferences.Add(Transformer.GeneratedMemoryPoolAssembly <TKey, TResult>()); assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(stream.Selector)); var a = Transformer.CompileSourceCode(expandedCode, assemblyReferences, out errorMessages); var t = a.GetType(generatedClassName); t = t.InstantiateAsNecessary(typeof(TKey), typeof(TPayload), typeof(TResult)); return(Tuple.Create(t, errorMessages)); } catch { if (Config.CodegenOptions.DontFallBackToRowBasedExecution) { throw new InvalidOperationException("Code Generation failed when it wasn't supposed to!"); } return(Tuple.Create((Type)null, errorMessages)); } }
internal static Tuple <Type, string> Generate <TKey, TLeft, TRight, TResult>( BinaryStreamable <TKey, TLeft, TRight, TResult> stream, Expression <Func <TLeft, TRight, TResult> > selector) { Contract.Requires(stream != null); Contract.Ensures(Contract.Result <Tuple <Type, string> >() == null || typeof(BinaryPipe <TKey, TLeft, TRight, TResult>).GetTypeInfo().IsAssignableFrom(Contract.Result <Tuple <Type, string> >().Item1)); string errorMessages = null; try { var template = new EquiJoinTemplate(); var keyType = template.keyType = typeof(TKey); var leftType = template.leftType = typeof(TLeft); var rightType = template.rightType = typeof(TRight); var resultType = template.resultType = typeof(TResult); var tm = new TypeMapper(keyType, leftType, rightType, resultType); template.TKey = tm.CSharpNameFor(keyType); template.TLeft = tm.CSharpNameFor(leftType); template.TRight = tm.CSharpNameFor(rightType); template.TResult = tm.CSharpNameFor(resultType); var keyAndLeftGenericParameters = tm.GenericTypeVariables(keyType, leftType).BracketedCommaSeparatedString(); var keyAndRightGenericParameters = tm.GenericTypeVariables(keyType, rightType).BracketedCommaSeparatedString(); template.TKeyTResultGenericParameters = tm.GenericTypeVariables(keyType, resultType).BracketedCommaSeparatedString(); template.genericParameters = tm.GenericTypeVariables(keyType, leftType, rightType, resultType).BracketedCommaSeparatedString(); template.className = string.Format("GeneratedEquiJoin_{0}", EquiJoinSequenceNumber++); template.leftMessageRepresentation = new ColumnarRepresentation(leftType); template.rightMessageRepresentation = new ColumnarRepresentation(rightType); var resultMessageRepresentation = new ColumnarRepresentation(resultType); var batchGeneratedFrom_TKey_TLeft = Transformer.GetBatchClassName(keyType, leftType); var batchGeneratedFrom_TKey_TRight = Transformer.GetBatchClassName(keyType, rightType); template.BatchGeneratedFrom_TKey_TResult = Transformer.GetBatchClassName(keyType, resultType); template.LeftBatchType = batchGeneratedFrom_TKey_TLeft + keyAndLeftGenericParameters; template.RightBatchType = batchGeneratedFrom_TKey_TRight + keyAndRightGenericParameters; template.leftFields = template.leftMessageRepresentation.AllFields; template.rightFields = template.rightMessageRepresentation.AllFields; template.resultFields = resultMessageRepresentation.AllFields; template.ActiveEventTypeLeft = leftType.GetTypeInfo().IsValueType ? template.TLeft : "Active_Event_Left"; template.ActiveEventTypeRight = rightType.GetTypeInfo().IsValueType ? template.TRight : "Active_Event_Right"; #region Key Equals var keyComparer = stream.Properties.KeyEqualityComparer.GetEqualsExpr(); template.keyComparerEquals = (left, right) => keyComparer.Inline(left, right); if (keyType.IsAnonymousType()) { template.keyComparerEquals = (left, right) => string.Format("keyComparerEquals({0}, {1})", left, right); } #endregion #region Left Payload Equals { var leftPayloadComparer = stream.Left.Properties.PayloadEqualityComparer.GetEqualsExpr(); var newLambda = Extensions.TransformFunction <TKey, TLeft>(leftPayloadComparer, "leftIndex", 0); template.leftComparerEquals = (left, right) => newLambda.Inline(left, right); } #endregion #region Right Payload Equals { var rightPayloadComparer = stream.Right.Properties.PayloadEqualityComparer.GetEqualsExpr(); var newLambda = Extensions.TransformFunction <TKey, TRight>(rightPayloadComparer, "rightIndex", 0); template.rightComparerEquals = (left, right) => newLambda.Inline(left, right); } #endregion #region Result Selector { var leftMessageType = StreamMessageManager.GetStreamMessageType <TKey, TLeft>(); var rightMessageType = StreamMessageManager.GetStreamMessageType <TKey, TRight>(); if (!ConstantExpressionFinder.IsClosedExpression(selector)) { errorMessages = "result selector is not a closed expression"; throw new InvalidOperationException(); } #region LeftBatchSelector { var parameterSubsitutions = new List <Tuple <ParameterExpression, SelectParameterInformation> >() { Tuple.Create(selector.Parameters[0], new SelectParameterInformation() { BatchName = "leftBatch", BatchType = leftMessageType, IndexVariableName = "i", parameterRepresentation = template.leftMessageRepresentation, }), }; var projectionResult = SelectTransformer.Transform(selector, parameterSubsitutions, resultMessageRepresentation, true); if (projectionResult.Error) { errorMessages = "error while transforming the result selector"; throw new InvalidOperationException(); } template.leftBatchSelector = (leftBatch, leftIndex, rightEvent) => { var d = new Dictionary <ParameterExpression, string> { { Expression.Variable(leftMessageType, "leftBatch"), leftBatch }, { Expression.Variable(typeof(int), "i"), leftIndex }, { selector.Parameters[1], rightEvent } }; var sb = new System.Text.StringBuilder(); sb.AppendLine("{"); foreach (var kv in projectionResult.ComputedFields) { var f = kv.Key; var e = kv.Value; if (f.OptimizeString()) { sb.AppendFormat( "output.{0}.AddString({1});\n", f.Name, e.ExpressionToCSharpStringWithParameterSubstitution(d)); } else { sb.AppendFormat( "output.{0}.col[index] = {1};\n", f.Name, e.ExpressionToCSharpStringWithParameterSubstitution(d)); } } sb.AppendLine("}"); return(sb.ToString()); }; } #endregion #region RightBatchSelector { var parameterSubsitutions = new List <Tuple <ParameterExpression, SelectParameterInformation> >() { Tuple.Create(selector.Parameters[1], new SelectParameterInformation() { BatchName = "rightBatch", BatchType = rightMessageType, IndexVariableName = "j", parameterRepresentation = template.rightMessageRepresentation, }), }; var projectionResult = SelectTransformer.Transform(selector, parameterSubsitutions, resultMessageRepresentation, true); if (projectionResult.Error) { errorMessages = "error while transforming the result selector"; throw new InvalidOperationException(); } template.rightBatchSelector = (leftEvent, rightBatch, rightIndex) => { var d = new Dictionary <ParameterExpression, string> { { selector.Parameters[0], leftEvent }, { Expression.Variable(rightMessageType, "rightBatch"), rightBatch }, { Expression.Variable(typeof(int), "j"), rightIndex } }; var sb = new System.Text.StringBuilder(); sb.AppendLine("{"); foreach (var kv in projectionResult.ComputedFields) { var f = kv.Key; var e = kv.Value; if (f.OptimizeString()) { sb.AppendFormat( "output.{0}.AddString({1});\n", f.Name, e.ExpressionToCSharpStringWithParameterSubstitution(d)); } else { sb.AppendFormat( "output.{0}.col[index] = {1};\n", f.Name, e.ExpressionToCSharpStringWithParameterSubstitution(d)); } } sb.AppendLine("}"); return(sb.ToString()); }; } #endregion #region ActiveSelector { var parameterSubsitutions = new List <Tuple <ParameterExpression, SelectParameterInformation> >(); var projectionResult = SelectTransformer.Transform(selector, parameterSubsitutions, resultMessageRepresentation, true); if (projectionResult.Error) { errorMessages = "error while transforming the result selector"; throw new InvalidOperationException(); } template.activeSelector = (leftEvent, rightEvent) => { var d = new Dictionary <ParameterExpression, string> { { selector.Parameters[0], leftEvent }, { selector.Parameters[1], rightEvent } }; var sb = new System.Text.StringBuilder(); sb.AppendLine("{"); foreach (var kv in projectionResult.ComputedFields) { var f = kv.Key; var e = kv.Value; if (f.OptimizeString()) { sb.AppendFormat( "output.{0}.AddString({1});\n", f.Name, e.ExpressionToCSharpStringWithParameterSubstitution(d)); } else { sb.AppendFormat( "output.{0}.col[index] = {1};\n", f.Name, e.ExpressionToCSharpStringWithParameterSubstitution(d)); } } sb.AppendLine("}"); return(sb.ToString()); }; } #endregion } #endregion if (stream.Left.Properties.IsIntervalFree && stream.Right.Properties.IsConstantDuration) { template.endPointHeap = "EndPointQueue"; } else if (stream.Right.Properties.IsIntervalFree && stream.Left.Properties.IsConstantDuration) { template.endPointHeap = "EndPointQueue"; } else if (stream.Left.Properties.IsConstantDuration && stream.Right.Properties.IsConstantDuration && stream.Left.Properties.ConstantDurationLength == stream.Right.Properties.ConstantDurationLength) { template.endPointHeap = "EndPointQueue"; } else { template.endPointHeap = "EndPointHeap"; } template.staticCtor = Transformer.StaticCtor(template.className); var expandedCode = template.TransformText(); var assemblyReferences = Transformer.AssemblyReferencesNeededFor(keyType, leftType, rightType, resultType); assemblyReferences.Add(typeof(IStreamable <,>).GetTypeInfo().Assembly); assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TLeft>()); assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TRight>()); assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TResult>()); var a = Transformer.CompileSourceCode(expandedCode, assemblyReferences, out errorMessages); if (keyType.IsAnonymousType()) { if (errorMessages == null) { errorMessages = string.Empty; } errorMessages += "\nCodegen Warning: The key type for an equi-join is an anonymous type (or contains an anonymous type), preventing the inlining of the key equality and hashcode functions. This may lead to poor performance.\n"; } var realClassName = template.className.AddNumberOfNecessaryGenericArguments(keyType, leftType, rightType, resultType); var t = a.GetType(realClassName); if (t.GetTypeInfo().IsGenericType) { var list = keyType.GetAnonymousTypes(); list.AddRange(leftType.GetAnonymousTypes()); list.AddRange(rightType.GetAnonymousTypes()); list.AddRange(resultType.GetAnonymousTypes()); return(Tuple.Create(t.MakeGenericType(list.ToArray()), errorMessages)); } else { return(Tuple.Create(t, errorMessages)); } } catch { if (Config.CodegenOptions.DontFallBackToRowBasedExecution) { throw new InvalidOperationException("Code Generation failed when it wasn't supposed to!"); } return(Tuple.Create((Type)null, errorMessages)); } }
/// <summary> /// Generate a batch class definition to be used as a Clip pipe. /// Compile the definition, dynamically load the assembly containing it, and return the Type representing the /// aggregate class. /// </summary> /// <typeparam name="TKey">The key type for both sides.</typeparam> /// <typeparam name="TLeft">The payload type for the left side.</typeparam> /// <typeparam name="TRight">The payload type for the right side.</typeparam> /// <returns> /// A type that is defined to be a subtype of BinaryPipe<<typeparamref name="TKey"/>,<typeparamref name="TLeft"/>, <typeparamref name="TKey"/>, <typeparamref name="TRight"/>>. /// </returns> internal static Tuple <Type, string> Generate <TKey, TLeft, TRight>(ClipJoinStreamable <TKey, TLeft, TRight> stream) { Contract.Requires(stream != null); Contract.Ensures(Contract.Result <Tuple <Type, string> >() == null || typeof(BinaryPipe <TKey, TLeft, TRight, TLeft>).GetTypeInfo().IsAssignableFrom(Contract.Result <Tuple <Type, string> >().Item1)); string errorMessages = null; try { var template = new ClipJoinTemplate(); var keyType = template.keyType = typeof(TKey); var leftType = template.leftType = typeof(TLeft); var rightType = template.rightType = typeof(TRight); var tm = new TypeMapper(keyType, leftType, rightType); template.TKey = tm.CSharpNameFor(keyType); template.TLeft = tm.CSharpNameFor(leftType); template.TRight = tm.CSharpNameFor(rightType); var gps = tm.GenericTypeVariables(keyType, leftType, rightType); template.genericParameters = gps.BracketedCommaSeparatedString(); template.className = string.Format("GeneratedClip_{0}", ClipSequenceNumber++); var resultRepresentation = new ColumnarRepresentation(leftType); template.ActiveEventType = leftType.GetTypeInfo().IsValueType ? template.TLeft : "Active_Event"; #region Key Comparer var keyComparer = stream.Properties.KeyEqualityComparer.GetEqualsExpr(); template.keyComparer = (left, right) => keyComparer.Inline(left, right); #endregion #region Left Comparer var leftComparer = stream.LeftComparer.GetEqualsExpr(); var newLambda = Extensions.TransformFunction <TKey, TLeft>(leftComparer, "index_ProcessLeftEvent", 0); template.leftComparer = (left, right) => newLambda.Inline(left, right); #endregion template.BatchGeneratedFrom_TKey_TLeft = Transformer.GetBatchClassName(keyType, leftType); template.TKeyTLeftGenericParameters = tm.GenericTypeVariables(keyType, leftType).BracketedCommaSeparatedString(); template.BatchGeneratedFrom_TKey_TRight = Transformer.GetBatchClassName(keyType, rightType); template.TKeyTRightGenericParameters = tm.GenericTypeVariables(keyType, rightType).BracketedCommaSeparatedString(); template.leftFields = resultRepresentation.AllFields; template.noFields = resultRepresentation.noFields; template.staticCtor = Transformer.StaticCtor(template.className); var expandedCode = template.TransformText(); var assemblyReferences = Transformer.AssemblyReferencesNeededFor(typeof(TKey), typeof(TLeft), typeof(TRight)); assemblyReferences.Add(typeof(IStreamable <,>).GetTypeInfo().Assembly); assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TLeft>()); assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TRight>()); assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(leftComparer)); var a = Transformer.CompileSourceCode(expandedCode, assemblyReferences, out errorMessages); var realClassName = template.className.AddNumberOfNecessaryGenericArguments(keyType, leftType, rightType); var t = a.GetType(realClassName); if (t.GetTypeInfo().IsGenericType) { var list = keyType.GetAnonymousTypes(); list.AddRange(leftType.GetAnonymousTypes()); list.AddRange(rightType.GetAnonymousTypes()); return(Tuple.Create(t.MakeGenericType(list.ToArray()), errorMessages)); } else { return(Tuple.Create(t, errorMessages)); } } catch { if (Config.CodegenOptions.DontFallBackToRowBasedExecution) { throw new InvalidOperationException("Code Generation failed when it wasn't supposed to!"); } return(Tuple.Create((Type)null, errorMessages)); } }
private static Tuple <Type, string> Generate <TKey, TSource, TResult>( string ingressType, string partitionString, Expression <Func <TSource, TKey> > partitionExpression, Expression <Func <TSource, long> > startEdgeExpression, Expression <Func <TSource, long> > endEdgeExpression, string latencyOption, string diagnosticOption, FuseModule fuseModule) { var template = new TemporalIngressTemplate( $"GeneratedTemporalIngress_{TemporalIngressSequenceNumber++}", typeof(TKey), typeof(TSource), fuseModule?.OutputType ?? typeof(TResult)); var tm = new TypeMapper(template.keyType, template.payloadType, template.resultType); var gps = tm.GenericTypeVariables(template.keyType, template.payloadType); template.genericParameters = gps.BracketedCommaSeparatedString(); template.payloadOrResult = tm.CSharpNameFor(template.resultRepresentation.RepresentationFor); var batchGeneratedFrom_TKey_TPayload = string.IsNullOrEmpty(partitionString) ? Transformer.GetBatchClassName(template.keyType, template.resultType) : Transformer.GetBatchClassName(typeof(PartitionKey <TKey>), template.resultType); var keyAndPayloadGenericParameters = tm.GenericTypeVariables(template.keyType, template.resultType).BracketedCommaSeparatedString(); template.GeneratedBatchName = batchGeneratedFrom_TKey_TPayload + keyAndPayloadGenericParameters; template.keyOrNothing = string.IsNullOrEmpty(partitionString) ? string.Empty : template.TKey + ", "; template.diagnosticOption = diagnosticOption; template.needsStreamEvent = ingressType == "StreamEvent"; template.genericArguments = (string.IsNullOrEmpty(partitionString) ? string.Empty : template.TKey + ", ") + template.TPayload; template.adjustedGenericArgs = (string.IsNullOrEmpty(partitionString) ? string.Empty : template.TKey + ", ") + (!fuseModule.IsEmpty && Config.AllowFloatingReorderPolicy ? template.TResult : template.TPayload); template.emptyOrPartition = string.IsNullOrEmpty(partitionString) ? "Microsoft.StreamProcessing.Empty.Default" : "new PartitionKey<" + template.TKey + ">(value.PartitionKey)"; template.partitionString = partitionString; template.baseStructure = partitionString + "StreamEvent<" + template.genericArguments + ">"; template.inheritBase = (ingressType != "StreamEvent") ? template.TPayload : template.baseStructure; template.ingressType = ingressType; template.latencyOption = latencyOption; template.partitionFunction = x => partitionExpression == null ? string.Empty : partitionExpression.Body.ExpressionToCSharpStringWithParameterSubstitution( new Dictionary <ParameterExpression, string> { { partitionExpression.Parameters.Single(), x } }); template.startEdgeFunction = x => startEdgeExpression == null ? string.Empty : startEdgeExpression.Body.ExpressionToCSharpStringWithParameterSubstitution( new Dictionary <ParameterExpression, string> { { startEdgeExpression.Parameters.Single(), x } }); template.endEdgeFunction = x => endEdgeExpression == null ? "StreamEvent.InfinitySyncTime" : endEdgeExpression.Body.ExpressionToCSharpStringWithParameterSubstitution( new Dictionary <ParameterExpression, string> { { endEdgeExpression.Parameters.Single(), x } }); template.fusionOption = fuseModule.IsEmpty ? "Simple" : (Config.AllowFloatingReorderPolicy ? "Disordered" : "Fused"); template.resultMightBeNull = template.resultType.CanContainNull(); Expression[] expressions = null; if (!fuseModule.IsEmpty) { template.valueString = fuseModule.Coalesce <TSource, TResult, TKey>("value.SyncTime", "value.OtherTime", "value.Payload", template.emptyOrPartition, out template.leadingText, out template.trailingText); template.generatedEndTimeVariable = "generatedEndTimeVariable"; if (Config.AllowFloatingReorderPolicy) { template.valueString = "value.Payload"; template.generatedEndTimeVariable = "value.OtherTime"; } expressions = fuseModule.GetCodeGenExpressions(); } return(template.Generate <TKey, TSource, TResult>(new Type[] { typeof(IStreamable <,>) }, expressions)); }
internal static Tuple <Type, string> Generate <TKey, TLeft, TRight, TResult>( BinaryStreamable <TKey, TLeft, TRight, TResult> stream, Expression <Func <TLeft, TRight, TResult> > selector) { Contract.Requires(stream != null); Contract.Ensures(Contract.Result <Tuple <Type, string> >() == null || typeof(BinaryPipe <TKey, TLeft, TRight, TResult>).GetTypeInfo().IsAssignableFrom(Contract.Result <Tuple <Type, string> >().Item1)); string errorMessages = null; try { var template = new StartEdgeEquiJoinTemplate(); var keyType = template.keyType = typeof(TKey); var leftType = template.leftType = typeof(TLeft); var rightType = template.rightType = typeof(TRight); var resultType = template.resultType = typeof(TResult); var tm = new TypeMapper(keyType, leftType, rightType, resultType); template.TKey = tm.CSharpNameFor(keyType); template.TLeft = tm.CSharpNameFor(leftType); template.TRight = tm.CSharpNameFor(rightType); template.TResult = tm.CSharpNameFor(resultType); var gps = tm.GenericTypeVariables(keyType, leftType, rightType, resultType); template.genericParameters = gps.BracketedCommaSeparatedString(); template.className = string.Format("GeneratedStartEdgeEquiJoin_{0}", StartEdgeEquiJoinSequenceNumber++); template.leftMessageRepresentation = new ColumnarRepresentation(leftType); template.leftFields = template.leftMessageRepresentation.AllFields; template.rightMessageRepresentation = new ColumnarRepresentation(rightType); template.rightFields = template.rightMessageRepresentation.AllFields; var outputMessageRepresentation = new ColumnarRepresentation(resultType); var resultRepresentation = outputMessageRepresentation; #region Key Comparer var keyComparer = stream.Properties.KeyEqualityComparer.GetEqualsExpr(); template.keyComparer = (left, right) => keyComparer.Inline(left, right); #endregion template.BatchGeneratedFrom_TKey_TLeft = Transformer.GetBatchClassName(keyType, leftType); template.TKeyTLeftGenericParameters = tm.GenericTypeVariables(keyType, leftType).BracketedCommaSeparatedString(); template.BatchGeneratedFrom_TKey_TRight = Transformer.GetBatchClassName(keyType, rightType); template.TKeyTRightGenericParameters = tm.GenericTypeVariables(keyType, rightType).BracketedCommaSeparatedString(); template.BatchGeneratedFrom_TKey_TResult = Transformer.GetBatchClassName(keyType, resultType); template.TKeyTResultGenericParameters = tm.GenericTypeVariables(keyType, resultType).BracketedCommaSeparatedString(); template.outputFields = resultRepresentation.AllFields; var leftMessageType = StreamMessageManager.GetStreamMessageType <TKey, TLeft>(); var rightMessageType = StreamMessageManager.GetStreamMessageType <TKey, TRight>(); #region LeftBatchSelector { var parameterSubsitutions = new List <Tuple <ParameterExpression, SelectParameterInformation> >() { Tuple.Create(selector.Parameters[0], new SelectParameterInformation() { BatchName = "leftBatch", BatchType = leftMessageType, IndexVariableName = "i", parameterRepresentation = template.leftMessageRepresentation, }), }; var projectionResult = SelectTransformer.Transform(selector, parameterSubsitutions, resultRepresentation, true); if (projectionResult.Error) { errorMessages = "error while transforming the result selector"; throw new InvalidOperationException(); } template.leftBatchSelector = (leftBatch, leftIndex, rightEvent) => { var d = new Dictionary <ParameterExpression, string> { { Expression.Variable(leftMessageType, "leftBatch"), leftBatch }, { Expression.Variable(typeof(int), "i"), leftIndex }, { selector.Parameters[1], rightEvent } }; var sb = new System.Text.StringBuilder(); sb.AppendLine("{"); foreach (var kv in projectionResult.ComputedFields) { var f = kv.Key; var e = kv.Value; if (f.OptimizeString()) { sb.AppendFormat( "output.{0}.AddString({1});\n", f.Name, e.ExpressionToCSharpStringWithParameterSubstitution(d)); } else { sb.AppendFormat( "output.{0}.col[index] = {1};\n", f.Name, e.ExpressionToCSharpStringWithParameterSubstitution(d)); } } sb.AppendLine("}"); return(sb.ToString()); }; } #endregion #region RightBatchSelector { var parameterSubsitutions = new List <Tuple <ParameterExpression, SelectParameterInformation> >() { Tuple.Create(selector.Parameters[1], new SelectParameterInformation() { BatchName = "rightBatch", BatchType = rightMessageType, IndexVariableName = "j", parameterRepresentation = template.rightMessageRepresentation, }), }; var projectionResult = SelectTransformer.Transform(selector, parameterSubsitutions, resultRepresentation, true); if (projectionResult.Error) { errorMessages = "error while transforming the result selector"; throw new InvalidOperationException(); } template.rightBatchSelector = (leftEvent, rightBatch, rightIndex) => { var d = new Dictionary <ParameterExpression, string> { { selector.Parameters[0], leftEvent }, { Expression.Variable(rightMessageType, "rightBatch"), rightBatch }, { Expression.Variable(typeof(int), "j"), rightIndex } }; var sb = new System.Text.StringBuilder(); sb.AppendLine("{"); foreach (var kv in projectionResult.ComputedFields) { var f = kv.Key; var e = kv.Value; if (f.OptimizeString()) { sb.AppendFormat( "output.{0}.AddString({1});\n", f.Name, e.ExpressionToCSharpStringWithParameterSubstitution(d)); } else { sb.AppendFormat( "output.{0}.col[index] = {1};\n", f.Name, e.ExpressionToCSharpStringWithParameterSubstitution(d)); } } sb.AppendLine("}"); return(sb.ToString()); }; } #endregion template.staticCtor = Transformer.StaticCtor(template.className); var expandedCode = template.TransformText(); var assemblyReferences = Transformer.AssemblyReferencesNeededFor(typeof(TKey), typeof(TLeft), typeof(TRight), typeof(TResult)); assemblyReferences.Add(typeof(IStreamable <,>).GetTypeInfo().Assembly); assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TLeft>()); assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TRight>()); assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TResult>()); assemblyReferences.Add(Transformer.GeneratedMemoryPoolAssembly <TKey, TResult>()); assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(selector)); var a = Transformer.CompileSourceCode(expandedCode, assemblyReferences, out errorMessages); var realClassName = template.className.AddNumberOfNecessaryGenericArguments(keyType, leftType, rightType, resultType); var t = a.GetType(realClassName); if (t.GetTypeInfo().IsGenericType) { var list = keyType.GetAnonymousTypes(); list.AddRange(leftType.GetAnonymousTypes()); list.AddRange(rightType.GetAnonymousTypes()); list.AddRange(resultType.GetAnonymousTypes()); return(Tuple.Create(t.MakeGenericType(list.ToArray()), errorMessages)); } else { return(Tuple.Create(t, errorMessages)); } } catch { if (Config.CodegenOptions.DontFallBackToRowBasedExecution) { throw new InvalidOperationException("Code Generation failed when it wasn't supposed to!"); } return(Tuple.Create((Type)null, errorMessages)); } }