// unary for us is the same as constant protected override Expression VisitUnary(UnaryExpression u) { /* * if(u.NodeType == ExpressionType.Convert) * { * // do constant here instead of convert * * _current.Clean = true; * _current.Exp = Expression.Constant(u.Operand); * _current.CurrentType = new SplitType(); * * return _current.Exp; * }else * { */ PushStatus(); Expression operand = this.Visit(u.Operand); CurentStatus currStatus = _current; PopStatus(); // if (operand != u.Operand) // { if (operand is ConstantExpression && u.NodeType == ExpressionType.Not) { // we have Not ( < constant > ) so => !<constant> _current.Clean = true; _current.Exp = u; _current.CurrentType = currStatus.CurrentType; string name = string.Format("!LU_{0}_{1}", (operand as ConstantExpression).Value, _literalSqnr++); _allLiterals.Add(name, new QLiteral() { Tag = name, Exp = u, SType = _current.CurrentType }); return(Expression.Constant(name)); } if (operand is ConstantExpression && u.NodeType == ExpressionType.Convert) { _current.Clean = true; _current.Exp = u; _current.CurrentType = currStatus.CurrentType; return(Expression.Constant(operand)); } // non trivial unary return(Expression.MakeUnary(u.NodeType, operand, u.Type, u.Method)); // } // return u; // } }
protected override Expression VisitMethodCall(MethodCallExpression m) { PushStatus(); //new current active if (!ReferenceEquals(null, m.Object)) { Expression obj = this.Visit(m.Object); } else { Expression obj = this.Visit(m.Arguments[m.Method.Name == "PatIndex" ? 1 : 0]); } CurentStatus methodStatus = _current; PopStatus(); //IEnumerable<Expression> args = this.VisitExpressionList(m.Arguments); if (_allowedFunctions.Contains(m.Method.Name)) { // allowed function _current.CurrentType = methodStatus.CurrentType; _current.Clean = true; _current.Exp = m; // we got literal so add it to parent string name = string.Format("LF_{0}_{1}", _current.CurrentType.Tag, _literalSqnr++); _allLiterals.Add(name, new QLiteral() { Tag = name, Exp = m, SType = _current.CurrentType }); return(Expression.Constant(name)); } return(m); }
protected override Expression VisitBinary(BinaryExpression b) { PushStatus(); //new current active Expression left = this.Visit(b.Left); CurentStatus leftStatus = _current; PopStatus(); //old current is up PushStatus(); //new current active Expression right = this.Visit(b.Right); CurentStatus rightStatus = _current; PopStatus(); if ( (left.NodeType == ExpressionType.MemberAccess && right.NodeType == ExpressionType.Constant) || (right.NodeType == ExpressionType.MemberAccess && left.NodeType == ExpressionType.Constant) ) { _current.CurrentType = ReferenceEquals(leftStatus.CurrentType.Type, null) ? rightStatus.CurrentType : leftStatus.CurrentType; _current.Clean = true; _current.Exp = b; string name = string.Format("LB_{0}_{1}", _current.CurrentType.Tag, _literalSqnr++); _allLiterals.Add(name, new QLiteral() { Tag = name, Exp = b, SType = _current.CurrentType }); return(Expression.Constant(name)); } else if (left.NodeType == ExpressionType.Constant && right.NodeType == ExpressionType.Constant) { // we did subst if ( // both null (ReferenceEquals(null, leftStatus.CurrentType.Type) && ReferenceEquals(null, rightStatus.CurrentType.Type) && leftStatus.Clean && rightStatus.Clean) || // or the same !ReferenceEquals(null, leftStatus.CurrentType.Type) && leftStatus.CurrentType.Type.Equals(rightStatus.CurrentType.Type) || // or there is clean type operated against constant with null type !ReferenceEquals(null, leftStatus.CurrentType.Type) && ReferenceEquals(null, rightStatus.CurrentType.Type) && rightStatus.Exp.NodeType == ExpressionType.Constant) { // remove current constants from literals, so we will not use them _allLiterals.Remove((left as ConstantExpression).Value.ToString()); _allLiterals.Remove((right as ConstantExpression).Value.ToString()); _current.CurrentType = leftStatus.CurrentType; _current.Clean = true; _current.Exp = b; // unify in new constant string name = string.Format("LB_{0}_{1}", _current.CurrentType.Tag, _literalSqnr++); _allLiterals.Add(name, new QLiteral() { Tag = name, Exp = b, SType = _current.CurrentType }); return(Expression.Constant(name)); } else { //return binary condition _current.CurrentType = new SplitType(); _current.Clean = false; _current.Exp = b; return(Expression.Constant(string.Format("({0}{1}{2})", (left as ConstantExpression).Value, GetStringRep(b), (right as ConstantExpression).Value))); //return Expression.MakeBinary(b.NodeType, left, right, b.IsLiftedToNull, b.Method); } } _current.CurrentType = new SplitType(); _current.Clean = false; _current.Exp = b; return(b); }
private CurentStatus PopStatus() { _current = _ctx.Pop(); return(_current); }
private CurentStatus PushStatus() { _ctx.Push(_current); _current = new CurentStatus(); return(_current); }
public List <Dictionary <Type, Expression> > Explode(Expression exp) { MethodInfo makeLambdaMethod = GetType().GetMethod("makeLambda"); _ctx = new Stack <CurentStatus>(); _current = new CurentStatus(); _result = this.Visit(exp); // reduce to DNF string expr = GetExpression(); if (expr.Length == 0) { List <Dictionary <Type, Expression> > ret = new List <Dictionary <Type, Expression> >(); ret.Add(new Dictionary <Type, Expression>()); return(ret); } // if not empty work! string nff = helper.ToDNF(expr); // now take or gorups string[] ors = nff.Split('|'); List <Dictionary <Type, Expression> > finalResult = new List <Dictionary <Type, Expression> >(); foreach (string OneAnd in ors) { string[] ands = OneAnd.Split('&'); // now we have single conditions in AND so take original expressions // and create n separate results of where condition Dictionary <Type, Expression> tmpResult = new Dictionary <Type, Expression>(); foreach (string lit in ands) { if (_allLiterals.ContainsKey(lit)) { QLiteral literal = _allLiterals[lit]; // if result for that SType exists do AND with it, // if not do new one, i this way we seaparate expressions for separate tables // and we can use join later // We have to do also type remaping // Expression newExpr = literal.SType.Type == typeof(object) ? literal.Exp : _remaper.remap(literal.Exp); Expression newExpr = _remaper.remap(literal.Exp, literal.SType); if (tmpResult.ContainsKey(literal.SType.Type)) { tmpResult[literal.SType.Type] = Expression.MakeBinary(ExpressionType.AndAlso, tmpResult[literal.SType.Type], newExpr); } else { tmpResult[literal.SType.Type] = newExpr; } } else { throw new Exception("Wrong DNF!"); } } Dictionary <Type, Expression> result = new Dictionary <Type, Expression>(); // make lambdas foreach (KeyValuePair <Type, Expression> p in tmpResult) { result[p.Key] = (Expression)makeLambdaMethod .MakeGenericMethod(p.Key) .Invoke(this, new object[] { p.Value, _splitTypes[p.Key].RootExpr } ); } finalResult.Add(result); } return(finalResult); }