/* Create a streamable for a 2-input reducer, with two 2-input mappers */ public IStreamable <TMapKey, TOutput> CreateStreamable <TMapInputLeft2, TMapInputRight2, TReduceInput2, TBind, TOutput>( IMapDefinition <TMapKey, TMapInputLeft2, TMapInputRight2, TReduceKey, TReduceInput2> imapDefinitionRight, Func <IStreamable <CompoundGroupKey <TMapKey, TReduceKey>, TReduceInput>, IStreamable <CompoundGroupKey <TMapKey, TReduceKey>, TReduceInput2>, IStreamable <CompoundGroupKey <TMapKey, TReduceKey>, TBind> > reducer, Expression <Func <GroupSelectorInput <TReduceKey>, TBind, TOutput> > resultSelector, OperationalHint reduceOptions) { Contract.Assume(sourceLeft != null); var mapDefinitionRight = (MapDefinition <TMapKey, TMapInputLeft2, TMapInputRight2, TReduceKey, TReduceInput2>)imapDefinitionRight; var sourceL1 = sourceLeft; var sourceR1 = sourceRight; var sourceL2 = mapDefinitionRight.sourceLeft; var sourceR2 = mapDefinitionRight.sourceRight; Expression <Func <TReduceKey, TBind, TOutput> > resultSelector2 = (k, b) => CallInliner.Call(resultSelector, new GroupSelectorInput <TReduceKey>(k), b); var inlinedResultSelector = resultSelector2.InlineCalls(); return(new Map2ReduceStreamable <TMapKey, TMapInputLeft, TMapInputRight, TMapInputLeft2, TMapInputRight2, TReduceKey, TReduceInput, TReduceInput2, TBind, TOutput>( sourceL1, sourceR1, mapper, keySelector, sourceL2, sourceR2, mapDefinitionRight.mapper, mapDefinitionRight.keySelector, reducer, inlinedResultSelector, leftAsymmetric, mapDefinitionRight.leftAsymmetric, reduceOptions)); }
public static IEqualityComparerExpression <T> GetCompoundEqualityComparerExpression <T, T1, T2, T3>(Expression <Func <T, T1> > lambda1, IEqualityComparerExpression <T1> iece1, Expression <Func <T, T2> > lambda2, IEqualityComparerExpression <T2> iece2, Expression <Func <T, T3> > lambda3, IEqualityComparerExpression <T3> iece3) { var iece1EqualsExpr = iece1.GetEqualsExpr(); var iece2EqualsExpr = iece2.GetEqualsExpr(); var iece3EqualsExpr = iece3.GetEqualsExpr(); Expression <Func <T, T, bool> > equalsTemplate = (left, right) => CallInliner.Call(iece1EqualsExpr, CallInliner.Call(lambda1, left), CallInliner.Call(lambda1, right)) && CallInliner.Call(iece2EqualsExpr, CallInliner.Call(lambda2, left), CallInliner.Call(lambda2, right)) && CallInliner.Call(iece3EqualsExpr, CallInliner.Call(lambda3, left), CallInliner.Call(lambda3, right)) ; var iece1HashExpr = iece1.GetGetHashCodeExpr(); var iece2HashExpr = iece2.GetGetHashCodeExpr(); var iece3HashExpr = iece3.GetGetHashCodeExpr(); Expression <Func <T, int> > hashTemplate = value => CallInliner.Call(iece1HashExpr, CallInliner.Call(lambda1, value)) ^ CallInliner.Call(iece2HashExpr, CallInliner.Call(lambda2, value)) ^ CallInliner.Call(iece3HashExpr, CallInliner.Call(lambda3, value)) ; return(new EqualityComparerExpression <T>(equalsTemplate.InlineCalls(), hashTemplate.InlineCalls())); }
/// <summary> /// Creates a new pattern without a register and adds a single-element transition that succeeds on stream elements that match a condition /// </summary> /// <typeparam name="TInput">The type of stream input data</typeparam> /// <param name="condition">The condition that must be met to consider the transition satisfied</param> /// <returns>A pattern whose first transition is the one just created</returns> public static Afa <TInput, Empty, bool> SingleElement <TInput>(Expression <Func <TInput, bool> > condition) { var afa = Afa.Create <TInput>(); Expression <Func <long, TInput, Empty, bool> > template = (ts, ev, r) => CallInliner.Call(condition, ev); afa.AddArc(0, 1, new SingleElementArc <TInput, Empty> { Fence = template.InlineCalls() }); afa.Seal(); return(afa); }
/// <summary> /// Filter input rows with the specified filter. /// </summary> public FilteredWindow <TKey, TSource> Where(Expression <Func <TSource, bool> > predicate) { Invariant.IsNotNull(predicate, nameof(predicate)); if (this.Filter == null) { return(new FilteredWindow <TKey, TSource>(predicate, this.Properties)); } Expression <Func <TSource, bool> > andedExpressionTemplate = input => CallInliner.Call(this.Filter, input) && CallInliner.Call(predicate, input); Expression <Func <TSource, bool> > andedExpression = andedExpressionTemplate.InlineCalls(); return(new FilteredWindow <TKey, TSource>(andedExpression, this.Properties)); }
public static IEqualityComparerExpression <T> GetEqualityComparerExpression <T, T1>( Expression <Func <T, T1> > lambda1, IEqualityComparerExpression <T1> iece1) { var iece1EqualsExpr = iece1.GetEqualsExpr(); Expression <Func <T, T, bool> > equalsTemplate = (left, right) => CallInliner.Call(iece1EqualsExpr, CallInliner.Call(lambda1, left), CallInliner.Call(lambda1, right)); var iece1HashExpr = iece1.GetGetHashCodeExpr(); Expression <Func <T, int> > hashTemplate = value => CallInliner.Call(iece1HashExpr, CallInliner.Call(lambda1, value)); return(new EqualityComparerExpression <T>(equalsTemplate.InlineCalls(), hashTemplate.InlineCalls())); }
public IStreamable <TMapKey, TOutput> CreateStreamable <TBind, TOutput>( Func <IStreamable <CompoundGroupKey <TMapKey, TReduceKey>, TReduceInput>, IStreamable <CompoundGroupKey <TMapKey, TReduceKey>, TBind> > reducer, Expression <Func <GroupSelectorInput <TReduceKey>, TBind, TOutput> > resultSelector) { Contract.Assume(this.sourceLeft != null); var sourceL = this.sourceLeft; var sourceR = this.sourceRight; Expression <Func <TReduceKey, TBind, TOutput> > resultSelector2 = (k, b) => CallInliner.Call(resultSelector, new GroupSelectorInput <TReduceKey>(k), b); Expression <Func <TReduceKey, TBind, TOutput> > inlinedResultSelector = resultSelector2.InlineCalls(); inlinedResultSelector = GroupInputAndKeyInliner <TReduceKey, TBind, TOutput> .Transform(inlinedResultSelector); return(new MapReduceStreamable <TMapKey, TMapInputLeft, TMapInputRight, TReduceKey, TReduceInput, TBind, TOutput>( sourceL, sourceR, this.mapper, this.keySelector, this.keyComparer, reducer, inlinedResultSelector, this.leftAsymmetric)); }
public IPattern <TKey, TPayload, TRegister, TAccumulator> SingleElement(Expression <Func <TPayload, bool> > condition, Expression <Func <TPayload, TRegister> > aggregator) { Expression <Func <long, TPayload, TRegister, bool> > conditionTemplate = (ts, ev, r) => CallInliner.Call(condition, ev); Expression <Func <long, TPayload, TRegister, TRegister> > aggregatorTemplate = (ts, ev, r) => CallInliner.Call(aggregator, ev); return(SingleElement(conditionTemplate.InlineCalls(), aggregatorTemplate.InlineCalls())); }
public IPattern <TKey, TPayload, TRegister, TAccumulator> ListElement(Expression <Func <List <TPayload>, bool> > condition, Expression <Func <long, List <TPayload>, TRegister, TRegister> > aggregator = null) { Expression <Func <long, List <TPayload>, TRegister, bool> > conditionTemplate = (ts, ev, r) => CallInliner.Call(condition, ev); return(ListElement(conditionTemplate.InlineCalls(), aggregator)); }
private static IPattern <TKey, TPayload, TRegister, TAccumulator> CreateMultiElementFunctions <TKey, TPayload, TRegister, TAccumulator>(IAbstractPatternRoot <TKey, TPayload, TRegister, TAccumulator> source, Expression <Func <TAccumulator> > accumulatorInitialization, Expression <Func <TAccumulator, bool> > accumulatorboolField, Expression <Func <long, TPayload, TRegister, bool> > fence, bool initialValueForBooleanField, Expression <Func <bool, bool> > shortCircuitCondition) { if (!(accumulatorboolField.Body is MemberExpression memberExpression)) { throw new InvalidOperationException("accumulatorboolField must be a lambda that picks out one field from its parameter"); } if (!(memberExpression.Expression is ParameterExpression parameter)) { throw new InvalidOperationException("accumulatorboolField must be a lambda that picks out one field from its parameter"); } var memberInfo = memberExpression.Member; if (memberInfo is System.Reflection.PropertyInfo propertyInfo && !propertyInfo.CanWrite) { throw new InvalidOperationException("accumulatorboolField is specifying a property, " + propertyInfo.Name + "' that does not have a setter"); } // "f" is the field specified by the accumulatorboolField lambda. // Create the Initialize function as (ts, reg) => { var acc = accumulatorInitialization(); acc.f = initialValueForBooleanField; return acc; } Expression <Func <long, TRegister, TAccumulator> > initializeTemplate = (ts, reg) => CallInliner.Call(accumulatorInitialization); var userInitializeFunction = initializeTemplate.InlineCalls(); var accumulatorLocalForInitialize = Expression.Parameter(typeof(TAccumulator), "acc"); var initializeBody = new List <Expression>() { Expression.Assign(accumulatorLocalForInitialize, userInitializeFunction.Body), Expression.Assign(Expression.MakeMemberAccess(accumulatorLocalForInitialize, memberInfo), Expression.Constant(initialValueForBooleanField, typeof(bool))), accumulatorLocalForInitialize }; var initializeFunction = (Expression <Func <long, TRegister, TAccumulator> >)Expression.Lambda( Expression.Block(new[] { accumulatorLocalForInitialize }, initializeBody), Expression.Parameter(typeof(long), "ts"), Expression.Parameter(typeof(TRegister), "reg")); // Create the Accumulate function as (ts, ev, reg, acc) => { acc.f = fence(ts, ev, reg); return acc; } Expression <Func <long, TPayload, TRegister, TAccumulator, bool> > userAccumulatorFunctionTemplate = (ts, ev, reg, acc) => CallInliner.Call(fence, ts, ev, reg); var userAccumulatorFunction = userAccumulatorFunctionTemplate.InlineCalls(); var accParmeter = userAccumulatorFunction.Parameters[3]; var accumulateBody = new List <Expression>() { Expression.Assign(Expression.MakeMemberAccess(accParmeter, memberInfo), userAccumulatorFunction.Body), accParmeter, }; var parameters = new ParameterExpression[] { userAccumulatorFunction.Parameters[0], userAccumulatorFunction.Parameters[1], userAccumulatorFunction.Parameters[2], accParmeter, }; var accumulateFunction = (Expression <Func <long, TPayload, TRegister, TAccumulator, TAccumulator> >)Expression.Lambda(Expression.Block(accumulateBody), parameters); // Create the SkipToEnd function as (ts, ev, acc) => acc.f Expression <Func <long, TPayload, TAccumulator, bool> > skipToEndTemplate = (ts, ev, acc) => CallInliner.Call(shortCircuitCondition, CallInliner.Call(accumulatorboolField, acc)); var skipToEndFunction = skipToEndTemplate.InlineCalls(); // Create the fence function as (ts, acc, reg) => acc.f Expression <Func <long, TAccumulator, TRegister, bool> > fenceTemplate = (ts, acc, reg) => CallInliner.Call(accumulatorboolField, acc); var fenceFunction = fenceTemplate.InlineCalls(); return(source.MultiElement(initializeFunction, accumulateFunction, skipToEndFunction, fenceFunction, null, null)); }
/// <summary> /// Add to the current pattern a new pattern symbol that matches all elements /// </summary> /// <typeparam name="TKey">Key type</typeparam> /// <typeparam name="TPayload">Payload type</typeparam> /// <typeparam name="TRegister">Result type (output of matcher is the register at an accepting state of the AFA)</typeparam> /// <param name="source">Input pattern</param> /// <param name="fence">Condition that must be true for the transition to occur</param> /// <returns>The newly constructed pattern</returns> public static IPattern <TKey, TPayload, TRegister, bool> AllElement <TKey, TPayload, TRegister>( this IAbstractPatternRoot <TKey, TPayload, TRegister, bool> source, Expression <Func <long, TPayload, TRegister, bool> > fence) { Expression <Func <long, TPayload, TRegister, bool, bool> > fenceTemplate = (ts, ev, reg, acc) => CallInliner.Call(fence, ts, ev, reg); return (source.MultiElement((ts, reg) => true, fenceTemplate.InlineCalls(), (ts, ev, acc) => !acc, (ts, acc, reg) => acc, null, null)); }
/// <summary> /// Creates a new pattern with a register and adds a single-element transition that succeeds on every stream element seen /// </summary> /// <typeparam name="TInput">The type of stream input data</typeparam> /// <typeparam name="TRegister">The type of the register to be mutated as transitions occur</typeparam> /// <param name="condition">The condition that must be met to consider the transition satisfied</param> /// <param name="aggregator">An aggregator mutator that sets the initial value of the register</param> /// <returns>A pattern with an updatable register whose first transition is the one just created</returns> public static Afa <TInput, TRegister, bool> SingleElement <TInput, TRegister>(Expression <Func <TInput, bool> > condition, Expression <Func <TInput, TRegister> > aggregator) { var afa = Afa.Create <TInput, TRegister>(); Expression <Func <long, TInput, TRegister, bool> > conditionTemplate = (ts, ev, r) => CallInliner.Call(condition, ev); Expression <Func <long, TInput, TRegister, TRegister> > aggregatorTemplate = (ts, ev, r) => CallInliner.Call(aggregator, ev); afa.AddArc(0, 1, new SingleElementArc <TInput, TRegister> { Fence = conditionTemplate.InlineCalls(), Transfer = aggregatorTemplate.InlineCalls(), }); afa.Seal(); return(afa); }
/// <summary> /// Creates a new pattern with a register and adds a time-synchronous list transition that succeeds on event lists that match a condition /// </summary> /// <typeparam name="TInput">The type of stream input data</typeparam> /// <typeparam name="TRegister">The type of the register to be mutated as transitions occur</typeparam> /// <param name="condition">The register-value sensitive condition that must be met to consider the transition satisfied</param> /// <returns>A pattern with an updatable register whose first transition is the one just created</returns> public static Afa <TInput, TRegister, bool> ListElement <TInput, TRegister>(Expression <Func <List <TInput>, TRegister, bool> > condition) { var afa = Afa.Create <TInput, TRegister>(); Expression <Func <long, List <TInput>, TRegister, bool> > conditionTemplate = (ts, ev, r) => CallInliner.Call(condition, ev, r); afa.AddArc(0, 1, new ListElementArc <TInput, TRegister> { Fence = conditionTemplate.InlineCalls(), }); afa.Seal(); return(afa); }