/// <summary>
        /// Two special cases for the right-hand side of an assignment or argument to a new expression where it turns into a column swing:
        ///    g = e_i.f
        ///        Then the projection for g turns into a swing of the column from f
        ///        E_i must be a decomposable type
        ///    g = e_i
        ///        The the projection for g turns into a swing of the pseudo-column for E_i
        ///        E_i must be an atomic type
        /// </summary>
        /// <returns>True iff the expression was transformed, either into a computed field or a swinging field.</returns>
        private bool HandleSimpleAssignments(Expression e, MyFieldInfo destinationColumn)
        {
            var simpleAssignedValue       = e as MemberExpression;
            ParameterExpression parameter = null;

            if (simpleAssignedValue != null)
            {
                parameter = simpleAssignedValue.Expression as ParameterExpression;
            }
            var paramIsForThisLambda = parameter != null && this.parameterInformation.ContainsKey(parameter);

            if (simpleAssignedValue != null && paramIsForThisLambda)
            {
                if (!this.parameterInformation.TryGetValue(parameter, out SelectParameterInformation spi))
                {
                    // if this particular parameter is not being substituted for, then the caller must not want it turned
                    // into anything. however, i think it might be an error situation and "this.error" should be set to true.
                    this.computedFields.Add(destinationColumn, simpleAssignedValue);
                    return(true);
                }
                var columnarField = spi.parameterRepresentation.Fields[simpleAssignedValue.Member.Name];
                if (this.noSwingingFields)
                {
                    var a = GetBatchColumnIndexer(parameter, columnarField);
                    this.computedFields.Add(destinationColumn, a);
                }
                else
                {
                    this.swingingFields.Add(Tuple.Create(destinationColumn, columnarField));
                }
                return(true);
            }
            parameter = e as ParameterExpression;
            if (parameter != null && this.parameterInformation.ContainsKey(parameter))
            {
                if (this.parameterInformation.TryGetValue(parameter, out SelectParameterInformation spi))
                {
                    var cr = spi.parameterRepresentation;
                    if (!cr.noFields)
                    {
                        this.error = true;
                        return(false);
                    }
                    if (this.noSwingingFields)
                    {
                        var a = GetBatchColumnIndexer(parameter, cr.PseudoField);
                        this.computedFields.Add(destinationColumn, a);
                    }
                    else
                    {
                        this.swingingFields.Add(Tuple.Create(destinationColumn, cr.PseudoField));
                    }
                    return(true);
                }
            }
            return(false);
        }
Beispiel #2
0
 protected static string ColumnPointerFieldAssignment(MyFieldInfo f, string batchName)
 {
     if (f.OptimizeString())
     {
         return(string.Format("this.{1}_{0}_col = {1}.{0};", f.Name, batchName));
     }
     else
     {
         return(string.Format("this.{1}_{0}_col = {1}.{0}.col;", f.Name, batchName));
     }
 }
Beispiel #3
0
 protected static string ColumnPointerFieldDeclaration(MyFieldInfo f, string batchName)
 {
     if (f.OptimizeString())
     {
         return(string.Format("Microsoft.StreamProcessing.Internal.Collections.Multistring {1}_{0}_col;", f.Name, batchName));
     }
     else
     {
         return(string.Format("{2} {1}_{0}_col;", f.Name, batchName, f.Type.MakeArrayType().GetCSharpSourceSyntax()));
     }
 }
Beispiel #4
0
 protected static string EndColumnPointerDeclaration(MyFieldInfo f)
 {
     if (f.canBeFixed)
     {
         return("}");
     }
     else
     {
         return(string.Empty);
     }
 }
Beispiel #5
0
        public ColumnarRepresentation(Type t)
        {
            this.RepresentationFor = t;
            var d = new Dictionary <string, MyFieldInfo>();

            this.Fields = d;
            foreach (var f in t.GetTypeInfo().GetFields(BindingFlags.Instance | BindingFlags.Public))
            {
                d.Add(f.Name, new MyFieldInfo(f /*, prefix*/));
            }

            // Any autoprops should be treated just as if they were a field
            foreach (var p in t.GetTypeInfo().GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                var getMethod = p.GetMethod;
                if (getMethod == null)
                {
                    continue;
                }
                if (!getMethod.IsDefined(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute)))
                {
                    continue;
                }
                var setMethod = p.SetMethod;
                if (setMethod == null)
                {
                    continue;
                }
                if (!setMethod.IsDefined(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute)))
                {
                    continue;
                }

                d.Add(p.Name, new MyFieldInfo(p /*, prefix*/));
            }

            if (!this.Fields.Any())
            {
                if (t.HasSupportedParameterizedConstructor())
                {
                    foreach (var p in t.GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance))
                    {
                        d.Add(p.Name, new MyFieldInfo(p /*, prefix*/));
                    }
                }
                else
                {
                    this.noFields    = true;
                    this.PseudoField = new MyFieldInfo(t, "payload");
                }
            }
        }
Beispiel #6
0
 protected static string BeginColumnPointerDeclaration(MyFieldInfo f, string batchName)
 {
     if (f.canBeFixed)
     {
         return(string.Format("fixed ({0}* {2}_{1}_col = {2}.{1}.col) {{", f.TypeName, f.Name, batchName));
     }
     else if (f.OptimizeString())
     {
         return(string.Format("var {1}_{0}_col = {1}.{0};", f.Name, batchName));
     }
     else
     {
         return(string.Format("var {1}_{0}_col = {1}.{0}.col;", f.Name, batchName));
     }
 }
        private IndexExpression GetBatchColumnIndexer(ParameterExpression parameter, MyFieldInfo f)
        {
            Contract.Requires(this.parameterInformation.ContainsKey(parameter));

            var parameterInfo = this.parameterInformation[parameter];
            var batch         = Expression.Variable(parameterInfo.BatchType, parameterInfo.BatchName);
            var column        = Expression.Field(batch, f.Name);
            var indexVariable = Expression.Variable(typeof(int), parameterInfo.IndexVariableName);

            if (column.Type.Equals(typeof(Internal.Collections.MultiString)))
            {
                var indexer = typeof(Internal.Collections.MultiString).GetTypeInfo().GetProperty("Item");
                return(Expression.MakeIndex(column, indexer, new List <Expression>()
                {
                    indexVariable
                }));
            }
            else
            {
                var colArray = Expression.Field(column, "col");
                return(Expression.ArrayAccess(colArray, indexVariable));
            }
        }
Beispiel #8
0
        public static Tuple <Type, string> Generate <TOuterKey, TSource, TInnerKey>(
            Expression <Func <TInnerKey, int> > hashComparer,
            Expression <Func <TSource, TInnerKey> > keySelector,
            bool nested)
        {
            var             typeOfTOuterKey = typeof(TOuterKey);
            var             typeOfTSource   = typeof(TSource);
            var             typeOfTInnerKey = typeof(TInnerKey);
            string          expandedCode;
            List <Assembly> assemblyReferences;
            string          errorMessages = null;

            try
            {
                string generatedClassName = $"GeneratedGroupStreamable_{GroupStreamableSequenceNumber++}";

                string      transformedKeySelectorAsString;
                MyFieldInfo swingingField = default;
                if (typeOfTInnerKey.IsAnonymousTypeName())
                {
                    Contract.Assume(keySelector.Body is NewExpression);
                    var transformedFunction = Extensions.TransformUnaryFunction <TOuterKey, TSource>(keySelector);
                    var newBody             = (NewExpression)transformedFunction.Body;
                    transformedKeySelectorAsString = string.Join(",", newBody.Arguments.Select(arg => arg.ExpressionToCSharp()));
                }
                else
                {
                    var body = keySelector.Body;

                    if (!nested && body is MemberExpression singleFieldProjection)
                    {
                        if (singleFieldProjection.Expression is ParameterExpression dereferencedObject)
                        {
                            // then can just swing a pointer to set the key of the result message
                            Contract.Assume(dereferencedObject == keySelector.Parameters.ElementAt(0));
                            var f = singleFieldProjection.Member;
                            var sourceMessageRepresentation = new ColumnarRepresentation(typeOfTSource);
                            var fieldToSwingFrom            = sourceMessageRepresentation.Fields[f.Name];
                            swingingField = fieldToSwingFrom;
                            transformedKeySelectorAsString = swingingField.Name + "_col[i]";
                        }
                        else
                        {
                            var transformedPredicate = Extensions.TransformUnaryFunction <TOuterKey, TSource>(keySelector).Body;
                            if (transformedPredicate == null)
                            {
                                return(Tuple.Create((Type)null, errorMessages));
                            }
                            transformedKeySelectorAsString = transformedPredicate.ExpressionToCSharp();
                        }
                    }
                    else
                    {
                        var transformedPredicate = Extensions.TransformUnaryFunction <TOuterKey, TSource>(keySelector).Body;

                        if (transformedPredicate == null)
                        {
                            return(Tuple.Create((Type)null, errorMessages));
                        }
                        transformedKeySelectorAsString = transformedPredicate.ExpressionToCSharp();
                    }
                }

                var inlinedHashCodeComputation = hashComparer.Inline("key");

                var template = new GroupTemplate(
                    generatedClassName,
                    typeOfTOuterKey,
                    typeOfTSource,
                    typeOfTInnerKey,
                    transformedKeySelectorAsString,
                    inlinedHashCodeComputation,
                    nested)
                {
                    swingingField      = swingingField,
                    payloadMightBeNull = typeOfTSource.CanContainNull()
                };

                if (!nested && Config.UseMultiString &&
                    typeOfTInnerKey.Equals(typeof(string)) &&
                    keySelector.IsSimpleFieldOrPropertyAccess())
                {
                    var transformedPredicate = Extensions.TransformUnaryFunction <TOuterKey, TSource>(keySelector).Body;
                    template.transformedKeySelectorAsString = transformedPredicate.ExpressionToCSharp();
                    template.inlinedHashCodeComputation     = "hashCodeVector.col[i]";
                    var fieldName = ((MemberExpression)keySelector.Body).Member.Name;
                    template.vectorHashCodeInitialization = $"resultBatch.hash = {Transformer.ColumnFieldPrefix}{fieldName}_col.GetHashCode(batch.bitvector);";
                    template.swingingHashColumn           = true;
                }

                template.fields = new ColumnarRepresentation(typeOfTSource).AllFields;

                expandedCode = template.TransformText();

                assemblyReferences = Transformer.AssemblyReferencesNeededFor(typeOfTOuterKey, typeOfTSource, typeOfTInnerKey);
                assemblyReferences.Add(typeof(IStreamable <,>).GetTypeInfo().Assembly);
                assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TOuterKey, TSource>());
                if (nested)
                {
                    assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <CompoundGroupKey <TOuterKey, TInnerKey>, TSource>());
                    assemblyReferences.Add(Transformer.GeneratedMemoryPoolAssembly <CompoundGroupKey <TOuterKey, TInnerKey>, TSource>());
                }
                else
                {
                    assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TInnerKey, TSource>());
                    assemblyReferences.Add(Transformer.GeneratedMemoryPoolAssembly <TInnerKey, TSource>());
                }
                assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(keySelector));

                var a = Transformer.CompileSourceCode(expandedCode, assemblyReferences, out errorMessages);
                if (typeOfTInnerKey.IsAnonymousTypeName())
                {
                    if (errorMessages == null)
                    {
                        errorMessages = string.Empty;
                    }
                    errorMessages += "\nCodegen Warning: The inner key type for Group is anonymous, causing the use of Activator.CreateInstance in an inner loop. This will lead to poor performance.\n";
                }

                generatedClassName = generatedClassName.AddNumberOfNecessaryGenericArguments(typeOfTOuterKey, typeOfTSource, typeOfTInnerKey);
                var t = a.GetType(generatedClassName);
                t = t.InstantiateAsNecessary(typeOfTOuterKey, typeOfTSource, typeOfTInnerKey);

                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));
            }
        }
Beispiel #9
0
 public static bool OptimizeString(this MyFieldInfo field) => Config.UseMultiString && field.Type == typeof(string);
Beispiel #10
0
 public static string AccessExpressionForRowValue(this MyFieldInfo f, string batchVariableName, string indexVariableName)
 => string.Format(CultureInfo.InvariantCulture, "{0}.{1}{2}[{3}]", batchVariableName, f.Name, f.OptimizeString() ? string.Empty : ".col", indexVariableName);
Beispiel #11
0
 public ColumnarRepresentation(Type t, string pseudoFieldName)
 {
     this.RepresentationFor = t;
     this.noFields          = true;
     this.PseudoField       = new MyFieldInfo(t, pseudoFieldName);
 }
Beispiel #12
0
 protected static string ColumnPointerFieldAssignment(MyFieldInfo f, string batchName)
 => f.OptimizeString()
         ? string.Format("this.{1}_{0}_col = {1}.{0};", f.Name, batchName)
         : string.Format("this.{1}_{0}_col = {1}.{0}.col;", f.Name, batchName);
Beispiel #13
0
 protected static string EndColumnPointerDeclaration(MyFieldInfo f) => f.canBeFixed ? "}" : string.Empty;
Beispiel #14
0
 protected static string BeginColumnPointerDeclaration(MyFieldInfo f, string batchName)
 => f.canBeFixed
         ? string.Format("fixed ({0}* {2}_{1}_col = {2}.{1}.col) {{", f.TypeName, f.Name, batchName)
         : f.OptimizeString()
             ? string.Format("var {1}_{0}_col = {1}.{0};", f.Name, batchName)
             : string.Format("var {1}_{0}_col = {1}.{0}.col;", f.Name, batchName);