public Expr CompileIfStatement(ParseTreeNode parseNode) { //[0] - Condition //[1] - True Block //[2] - {ElseIf Statements} //[3] - [Else Block] bool hasElseIfs = parseNode.ChildNodes[2].ChildNodes.Any(); bool hasElse = parseNode.ChildNodes[3].ChildNodes.Any(); Expr ifStatement = Expr.Empty(); //Add else component if (hasElse) { ifStatement = CompileBlock(parseNode.ChildNodes[3]); } foreach (var elseIf in Enumerable.Reverse(parseNode.ChildNodes[2].ChildNodes)) { ifStatement = Expr.IfThenElse( TypeHelpers.ToBoolean(CompileExpression(elseIf.ChildNodes[0])), CompileBlock(elseIf.ChildNodes[1]), ifStatement); } ifStatement = Expr.IfThenElse( TypeHelpers.ToBoolean(CompileExpression(parseNode.ChildNodes[0])), CompileBlock(parseNode.ChildNodes[1]), ifStatement ); return(ifStatement); }
public void Lambda() { var expression = LinqExpression.Lambda(LinqExpression.Empty()); ShouldRoundrip(expression); }
public void TypeBinary_is() { var expression = LinqExpression.TypeIs( LinqExpression.Empty(), typeof(object)); ShouldRoundrip(expression); }
public void Empty() { var expected = LinqExpression.Empty(); using var g = new GraphEngine.Graph(); g.LoadFromString(@" @prefix : <http://example.com/> . :s a :Empty ; . "); var s = g.GetUriNode(":s"); var actual = Expression.Parse(s).LinqExpression; Console.WriteLine(actual.GetDebugView()); actual.Should().Be(expected); }
protected override Expression VisitConditional(ConditionalExpression node) { var test = Visit(node.Test); if (test.TryAsConst(out bool v)) { var result = Visit(v ? node.IfTrue : node.IfFalse); if (node.Type == typeof(void)) { //Don't change the return type return(Ex.Block(result, Ex.Empty())); } else { return(result); } } return(Expression.Condition(test, DeferWithNoReduction(base.Visit, node.IfTrue), DeferWithNoReduction(base.Visit, node.IfFalse), node.Type)); }
private static CloneDelegate <T> GetObjectCloner <T>(Type type, CloneContext context) { Delegate result; var cache = context.Cache; var key = new CacheKey(typeof(T), type); if (!cache.TryGetValue(key, out result)) { var statements = new List <LinqExpression>(); var param = LinqExpression.Parameter(typeof(T).MakeByRefType(), "input"); var output = LinqExpression.Parameter(typeof(T).MakeByRefType(), "output"); var contextParam = LinqExpression.Parameter(typeof(CloneContext), "context"); ParameterExpression localCast; ParameterExpression localOutput; ParameterExpression localObj; bool isStruct = type.IsValueType && typeof(T) == type; bool isArray = type.IsArray; if (isStruct || isArray) { localCast = param; localOutput = output; localObj = null; } else { localObj = LinqExpression.Variable(typeof(object), "localObj"); localCast = LinqExpression.Variable(type, "localCast"); localOutput = LinqExpression.Variable(type, "localOut"); statements.Add(LinqExpression.Assign(localCast, LinqExpression.Convert(param, type))); if (context.IsSelfClone) { statements.Add(LinqExpression.Call(contextParam, MethodAdd, param, param)); statements.Add(LinqExpression.Assign(output, localCast)); } else { // NOTE: this can fail if there is no default constructor for type. // for example Dictionary<K,T>.ValueCollection, which is created when a access to members Keys or Values is performed on the dicitonary. statements.Add(LinqExpression.Assign(localOutput, LinqExpression.New(type))); statements.Add(LinqExpression.Assign(output, localOutput)); statements.Add(LinqExpression.Call(contextParam, MethodAdd, param, localOutput)); } } var fields = GetFields(type); // If we have a struct with primitive only if (isArray) { var genericCloneMethod = DeepcloneArray.GetGenericMethodDefinition(); genericCloneMethod = genericCloneMethod.MakeGenericMethod(new[] { type.GetElementType() }); statements.Add(LinqExpression.Call(genericCloneMethod, localCast, localOutput, contextParam)); } else if (isStruct && fields.All(field => IsPrimitive(field.FieldType))) { statements.Add(LinqExpression.Assign(localOutput, param)); } else { foreach (var field in fields) { if (field.IsInitOnly) { throw new InvalidOperationException(String.Format("Field [{0}] in [{1}] is readonly, which is not supported in DeepClone", field.Name, type)); } var t = field.FieldType; if (t.IsSubclassOf(typeof(Delegate))) { continue; } var value = LinqExpression.Field(localCast, field); LinqExpression cloneField = null; if (IsPrimitive(t)) { if (!context.IsSelfClone) { cloneField = LinqExpression.Assign(LinqExpression.Field(localOutput, field), value); } } else { MethodInfo genericCloneMethod; if (field.FieldType.IsArray) { genericCloneMethod = DeepcloneArray.GetGenericMethodDefinition(); genericCloneMethod = genericCloneMethod.MakeGenericMethod(new[] { field.FieldType.GetElementType() }); } else { genericCloneMethod = DeepcloneObject.GetGenericMethodDefinition(); genericCloneMethod = genericCloneMethod.MakeGenericMethod(new[] { field.FieldType }); } cloneField = LinqExpression.Call(genericCloneMethod, value, context.IsSelfClone ? value : LinqExpression.Field(localOutput, field), contextParam); } if (cloneField != null) { statements.Add(cloneField); } } } LinqExpression body; if (isStruct || isArray) { if (statements.Count == 0) { body = LinqExpression.Empty(); } else { body = LinqExpression.Block(statements); } } else { var innerBody = LinqExpression.Block(new[] { localCast, localOutput }, statements); body = LinqExpression.Block( new[] { localObj }, LinqExpression.IfThenElse( LinqExpression.Call(contextParam, MethodTryGetValue, param, localObj), LinqExpression.Assign(output, LinqExpression.Convert(localObj, typeof(T))), innerBody)); } var tempLambda = LinqExpression.Lambda <CloneDelegate <T> >(body, param, output, contextParam); result = tempLambda.Compile(); cache.Add(key, result); } return((CloneDelegate <T>)result); }
public override SysExpr ToExpression() => Type == typeof(void) ? SysExpr.Empty() : SysExpr.Default(Type);
private static TDelegate Simdize <T, TDelegate>(LambdaExpression expr) where T : unmanaged where TDelegate : Delegate { if (_cache.TryGetValue(expr, out var value)) { return((TDelegate)value); } var simdVisitor = new SimdVisitor <T>(expr); var simdBody = simdVisitor.Visit(expr.Body); var i = Expr.Parameter(typeof(int), "i"); var len = Expr.Parameter(typeof(int), "len"); var xMemories = expr.Parameters.Select(p => Expr.Parameter(typeof(ReadOnlyMemory <T>), p.Name)).ToArray(); var resultMemory = Expr.Parameter(typeof(Memory <T>), "result"); var xSpans = xMemories.Select(p => Expr.Variable(typeof(ReadOnlySpan <T>), $"{p.Name}Span")).ToArray(); var resultSpan = Expr.Variable(typeof(Span <T>), "resultSpan"); var xVecSpans = xMemories.Select(p => Expr.Variable(typeof(ReadOnlySpan <Vector <T> >), $"{p.Name}VecSpan")).ToArray(); var resultVecSpan = Expr.Variable(typeof(Span <Vector <T> >), "resultVecSpan"); var xSpanGetters = xSpans.Select(p => Expr.Call(null, MemberTable._ReadOnlySpan <T> .GetItem, p, i)).ToArray(); var xVecSpanGetters = xVecSpans.Select(p => Expr.Call(null, MemberTable._ReadOnlySpan <Vector <T> > .GetItem, p, i)).ToArray(); var exprCall = new LambdaArgsVisitor(expr.Parameters.Zip(xSpanGetters).ToDictionary(tpl => tpl.Item1, tpl => (Expr)tpl.Item2)).Visit(expr.Body); var simdCall = new LambdaArgsVisitor(simdVisitor.NewArguments.Zip(xVecSpanGetters).ToDictionary(tpl => tpl.Item1, tpl => (Expr)tpl.Item2)).Visit(simdBody); var resultSpanSetter = Expr.Call(null, MemberTable._Span <T> .SetItem, resultSpan, i, exprCall); var resultVecSpanSetter = Expr.Call(null, MemberTable._Span <Vector <T> > .SetItem, resultVecSpan, i, simdCall); var parameters = xMemories.Concat(new[] { resultMemory }); var variables = xSpans.Concat(xVecSpans).Concat(new[] { i, len, resultSpan, resultVecSpan }); var block = new List <Expr>(); // xSpan = xMemory.Span; block.AddRange(xMemories.Zip(xSpans, (memory, span) => Expr.Assign( span, Expr.Property(memory, MemberTable._ReadOnlyMemory <T> .Span) ) )); // xVecSpan = MemoryMarshal.Cast<T, Vector<T>>(xSpan); block.AddRange(xSpans.Zip(xVecSpans, (span, vSpan) => Expr.Assign( vSpan, Expr.Call(null, MemberTable._MemoryMarshal.Cast <T, Vector <T> > .ForReadOnlySpan, span) ) )); // resultSpan = resultMemory.Span; block.Add( Expr.Assign( resultSpan, Expr.Property(resultMemory, MemberTable._Memory <T> .Span) ) ); // resultVecSpan = MemoryMarshal.Cast<T, Vector<T>>(resultSpan); block.Add( Expr.Assign( resultVecSpan, Expr.Call(null, MemberTable._MemoryMarshal.Cast <T, Vector <T> > .ForSpan, resultSpan) ) ); // for(i = 0, len = resultVecSpan.Length & ~0b1111; i < len; ) // { // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x0 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x1 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x2 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x3 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x4 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x5 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x6 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x7 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x8 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x9 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0xA // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0xB // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0xC // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0xD // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0xE // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0xF // } block.Add( ExpressionEx.For( Expr.Block( Expr.Assign(i, Expr.Constant(0)), Expr.Assign( len, Expr.And(Expr.Property(resultVecSpan, MemberTable._Span <Vector <T> > .Length), Expr.Constant(~0b1111)) ) ), Expr.LessThan(i, len), Expr.Empty(), Expr.Block( resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x0 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x1 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x2 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x3 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x4 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x5 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x6 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x7 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x8 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x9 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0xA resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0xB resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0xC resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0xD resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0xE resultVecSpanSetter, Expr.PreIncrementAssign(i) // 0xF ) ) ); // if(i < (resultVecSpan.Length & ~0b111)) // { // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x0 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x1 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x2 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x3 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x4 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x5 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x6 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x7 // } block.Add( Expr.IfThen( Expr.LessThan( i, Expr.And(Expr.Property(resultVecSpan, MemberTable._Span <Vector <T> > .Length), Expr.Constant(~0b111)) ), Expr.Block( resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x0 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x1 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x2 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x3 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x4 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x5 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x6 resultVecSpanSetter, Expr.PreIncrementAssign(i) // 0x7 ) ) ); // if(i < (resultVecSpan.Length & ~0b11)) // { // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x0 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x1 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x2 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x3 // } block.Add( Expr.IfThen( Expr.LessThan( i, Expr.And(Expr.Property(resultVecSpan, MemberTable._Span <Vector <T> > .Length), Expr.Constant(~0b11)) ), Expr.Block( resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x0 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x1 resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x2 resultVecSpanSetter, Expr.PreIncrementAssign(i) // 0x3 ) ) ); // if(i < (resultVecSpan.Length & ~0b1)) // { // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x0 // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x1 // } block.Add( Expr.IfThen( Expr.LessThan( i, Expr.And(Expr.Property(resultVecSpan, MemberTable._Span <Vector <T> > .Length), Expr.Constant(~0b1)) ), Expr.Block( resultVecSpanSetter, Expr.PreIncrementAssign(i), // 0x0 resultVecSpanSetter, Expr.PreIncrementAssign(i) // 0x1 ) ) ); // if(i < resultVecSpan.Length) // { // resultVecSpan[i] = simdCall(xVecSpan[i], ...); ++i; // 0x0 // } block.Add( Expr.IfThen( Expr.LessThan( i, Expr.Property(resultVecSpan, MemberTable._Span <Vector <T> > .Length) ), Expr.Block( resultVecSpanSetter, Expr.PreIncrementAssign(i) // 0x0 ) ) ); // for(i = Vector<T>.Count * resultVecSpan.Length; i < resultSpan.Length; ) // { // resultSpan[i] = exprCall(xSpan[i], ...); ++i; // } block.Add( ExpressionEx.For( Expr.Assign( i, Expr.Multiply( Expr.Constant(Vector <T> .Count), Expr.Property(resultVecSpan, MemberTable._Span <Vector <T> > .Length) ) ), Expr.LessThan(i, Expr.Property(resultSpan, MemberTable._Span <T> .Length)), Expr.Empty(), Expr.Block( resultSpanSetter, Expr.PreIncrementAssign(i) ) ) ); var retval = Expr.Lambda <TDelegate>(Expr.Block(variables, block), parameters).Compile(); _cache.TryAdd(expr, retval); return(retval); }
public void Empty() { var expression = LinqExpression.Empty(); ShouldRoundrip(expression); }
/// <summary> /// Creates a <see cref="ConditionalExpression"/>. /// </summary> /// <param name="test">An <see cref="Expression"/> to set the <see cref="ConditionalExpression.Test"/> property equal to.</param> /// <param name="ifTrue">An <see cref="Expression"/> to set the <see cref="ConditionalExpression.IfTrue"/> property equal to.</param> /// <returns>A <see cref="ConditionalExpression"/> that has the <see cref="NodeType"/> property equal to /// <see cref="ExpressionType.Conditional"/> and the <see cref="ConditionalExpression.Test"/>, <see cref="ConditionalExpression.IfTrue"/>, /// properties set to the specified values. The <see cref="ConditionalExpression.IfFalse"/> property is set to default expression and /// the type of the resulting <see cref="ConditionalExpression"/> returned by this method is <see cref="Void"/>.</returns> public static ConditionalExpression IfThen(Expression test, Expression ifTrue) { return(Condition(test, ifTrue, Expression.Empty(), typeof(void))); }
internal virtual Expression GetFalse() { return(Expression.Empty()); }
public static Expression TryNoCatch(this Expression expression) => Expression.TryCatch(expression, Expression.Catch(typeof(Exception).ToParameter(), Expression.Empty()));
public virtual Expr ToExpression() { var blockBody = new List <Expr>(); #if EXPERIMENTAL_GENERATOR var variables = new HashSet <ParameterExpression>(); #endif // AccessExpression is null on the root node (It's a dummy node) // ReadExpression.Count > 1 can only happen if we decided to roll a loop, in which case all elements are identical. // ReadExpression.Count = 0 can happen if the type is a value type. Otherwise this is new T[...] or new T(). if (AccessExpression != null) { if (ReadExpression.Count > 0) { blockBody.Add(Expr.Assign(AccessExpression, ReadExpression[0])); } else if (TypeToken.IsArray) { blockBody.Add(Expr.Assign(AccessExpression, TypeToken.GetElementTypeToken().NewArrayBounds(Expr.Constant(MemberToken.Cardinality)))); } else if (TypeToken.IsClass) { if (!TypeToken.HasDefaultConstructor) { throw new InvalidOperationException("Missing default constructor for " + TypeToken.Name); } blockBody.Add(Expr.Assign(AccessExpression, TypeToken.NewExpression())); } } if (Children.Count > 0) { // Produce children if there are any foreach (var child in Children) { var subExpression = child.ToExpression(); #if EXPERIMENTAL_GENERATOR if (subExpression is BlockExpression subBlockExpression) { blockBody.AddRange(subBlockExpression.Expressions); foreach (var subBlockVariable in subBlockExpression.Variables) { variables.Add(subBlockVariable); } } else { blockBody.Add(subExpression); } #else blockBody.Add(subExpression); #endif } // Assert that there is at least one node in the block emitted. if (blockBody.Count == 0) { throw new InvalidOperationException("Empty block"); } } // We allow empty blocks if there are no children for primitive types if (blockBody.Count == 0) { return(Expr.Empty()); } // If there's only one expression, just return it. #if EXPERIMENTAL_GENERATOR if (blockBody.Count == 1 && variables.Count == 0) { return(blockBody[0]); } return(Expression.Block(variables, blockBody)); #else if (blockBody.Count == 1) { return(blockBody[0]); } return(Expr.Block(blockBody)); #endif }