예제 #1
0
        // 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;

            // }
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
 private CurentStatus PopStatus()
 {
     _current = _ctx.Pop();
     return(_current);
 }
예제 #5
0
 private CurentStatus PushStatus()
 {
     _ctx.Push(_current);
     _current = new CurentStatus();
     return(_current);
 }
예제 #6
0
        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);
        }