public Code Pow(Code opd1, Code opd2)
        {
            Node left  = (Node)opd1;
            Node right = (Node)opd2;

            if (left.type == NodeType.tpReal || right.type == NodeType.tpReal)
            {
                if (left.type == NodeType.tpInt)
                {
                    left = QueryImpl.int2real(left);
                }
                else if (left.type != NodeType.tpReal)
                {
                    throw new CodeGeneratorException("Invalid argument types");
                }
                if (right.type == NodeType.tpInt)
                {
                    right = QueryImpl.int2real(right);
                }
                else if (right.type != NodeType.tpReal)
                {
                    throw new CodeGeneratorException("Invalid argument types");
                }
                return(new BinOpNode(NodeType.tpReal, NodeTag.opRealPow, left, right));
            }
            else if (left.type == NodeType.tpInt && right.type == NodeType.tpInt)
            {
                return(new BinOpNode(NodeType.tpInt, NodeTag.opIntPow, left, right));
            }
            else
            {
                throw new CodeGeneratorException("Invalid argument types");
            }
        }
        public Code Le(Code opd1, Code opd2)
        {
            Node left  = (Node)opd1;
            Node right = (Node)opd2;

            if (left.type == NodeType.tpReal || right.type == NodeType.tpReal)
            {
                if (left.type == NodeType.tpInt)
                {
                    left = QueryImpl.int2real(left);
                }
                else if (left.type != NodeType.tpReal)
                {
                    throw new CodeGeneratorException("Invalid argument types");
                }
                if (right.type == NodeType.tpInt)
                {
                    right = QueryImpl.int2real(right);
                }
                else if (right.type != NodeType.tpReal)
                {
                    throw new CodeGeneratorException("Invalid argument types");
                }
                return(new BinOpNode(NodeType.tpBool, NodeTag.opRealLe, left, right));
            }
            else if (left.type == NodeType.tpInt && right.type == NodeType.tpInt)
            {
                return(new BinOpNode(NodeType.tpBool, NodeTag.opIntLe, left, right));
            }
            else if (left.type == NodeType.tpStr && right.type == NodeType.tpStr)
            {
                return(new BinOpNode(NodeType.tpBool, NodeTag.opStrLe, left, right));
            }
            else if (left.type == NodeType.tpDate || right.type == NodeType.tpDate)
            {
                if (left.type == NodeType.tpStr)
                {
                    left = QueryImpl.str2date(left);
                }
                else if (left.type != NodeType.tpDate)
                {
                    throw new CodeGeneratorException("Invalid argument types");
                }
                if (right.type == NodeType.tpStr)
                {
                    right = QueryImpl.str2date(right);
                }
                else if (right.type != NodeType.tpDate)
                {
                    throw new CodeGeneratorException("Invalid argument types");
                }
                return(new BinOpNode(NodeType.tpBool, NodeTag.opDateLe, left, right));
            }
            else
            {
                throw new CodeGeneratorException("Invalid argument types");
            }
        }
        Node mathFunc(NodeTag cop, Code opd)
        {
            Node expr = (Node)opd;

            if (expr.type == NodeType.tpInt)
            {
                expr = QueryImpl.int2real(expr);
            }
            else if (expr.type != NodeType.tpReal)
            {
                throw new CodeGeneratorException("Invalid argument types");
            }
            return(new UnaryOpNode(NodeType.tpReal, cop, expr));
        }
        public Code Between(Code opd1, Code opd2, Code opd3)
        {
            Node expr = (Node)opd1;
            Node low  = (Node)opd2;
            Node high = (Node)opd3;

            if (expr.type == NodeType.tpReal || low.type == NodeType.tpReal || high.type == NodeType.tpReal)
            {
                if (expr.type == NodeType.tpInt)
                {
                    expr = QueryImpl.int2real(expr);
                }
                else if (expr.type != NodeType.tpReal)
                {
                    throw new CodeGeneratorException("Invalid argument types");
                }
                if (low.type == NodeType.tpInt)
                {
                    low = QueryImpl.int2real(low);
                }
                else if (low.type != NodeType.tpReal)
                {
                    throw new CodeGeneratorException("Invalid argument types");
                }
                if (high.type == NodeType.tpInt)
                {
                    high = QueryImpl.int2real(high);
                }
                else if (high.type != NodeType.tpReal)
                {
                    throw new CodeGeneratorException("Invalid argument types");
                }
                return(new CompareNode(NodeTag.opRealBetween, expr, low, high));
            }
            else if (expr.type == NodeType.tpInt && low.type == NodeType.tpInt && high.type == NodeType.tpInt)
            {
                return(new CompareNode(NodeTag.opIntBetween, expr, low, high));
            }
            else if (expr.type == NodeType.tpStr && low.type == NodeType.tpStr && high.type == NodeType.tpStr)
            {
                return(new CompareNode(NodeTag.opStrBetween, expr, low, high));
            }
            else if (expr.type == NodeType.tpDate)
            {
                if (low.type == NodeType.tpStr)
                {
                    low = QueryImpl.str2date(low);
                }
                else if (low.type != NodeType.tpDate)
                {
                    throw new CodeGeneratorException("Invalid argument types");
                }
                if (high.type == NodeType.tpStr)
                {
                    high = QueryImpl.str2date(high);
                }
                else if (high.type != NodeType.tpDate)
                {
                    throw new CodeGeneratorException("Invalid argument types");
                }
                return(new CompareNode(NodeTag.opDateBetween, expr, low, high));
            }
            else
            {
                throw new CodeGeneratorException("Invalid argument types");
            }
        }
        public Code In(Code opd1, Code opd2)
        {
            Node left  = (Node)opd1;
            Node right = (Node)opd2;

            if (right == null)
            {
                return(new ConstantNode(NodeType.tpBool, NodeTag.opFalse));
            }
            switch (right.type)
            {
            case NodeType.tpCollection:
                return(new BinOpNode(NodeType.tpBool, NodeTag.opScanCollection, left, right));

            case NodeType.tpArrayBool:
                return(new BinOpNode(NodeType.tpBool, NodeTag.opScanArrayBool, checkType(NodeType.tpBool, left), right));

            case NodeType.tpArrayChar:
                return(new BinOpNode(NodeType.tpBool, NodeTag.opScanArrayChar, checkType(NodeType.tpInt, left), right));

            case NodeType.tpArrayInt1:
                return(new BinOpNode(NodeType.tpBool, NodeTag.opScanArrayInt1, checkType(NodeType.tpInt, left), right));

            case NodeType.tpArrayInt2:
                return(new BinOpNode(NodeType.tpBool, NodeTag.opScanArrayInt2, checkType(NodeType.tpInt, left), right));

            case NodeType.tpArrayInt4:
                return(new BinOpNode(NodeType.tpBool, NodeTag.opScanArrayInt4, checkType(NodeType.tpInt, left), right));

            case NodeType.tpArrayInt8:
                return(new BinOpNode(NodeType.tpBool, NodeTag.opScanArrayInt8, checkType(NodeType.tpInt, left), right));

            case NodeType.tpArrayUInt1:
                return(new BinOpNode(NodeType.tpBool, NodeTag.opScanArrayUInt1, checkType(NodeType.tpInt, left), right));

            case NodeType.tpArrayUInt2:
                return(new BinOpNode(NodeType.tpBool, NodeTag.opScanArrayUInt2, checkType(NodeType.tpInt, left), right));

            case NodeType.tpArrayUInt4:
                return(new BinOpNode(NodeType.tpBool, NodeTag.opScanArrayUInt4, checkType(NodeType.tpInt, left), right));

            case NodeType.tpArrayUInt8:
                return(new BinOpNode(NodeType.tpBool, NodeTag.opScanArrayUInt8, checkType(NodeType.tpInt, left), right));

            case NodeType.tpArrayReal4:
                if (left.type == NodeType.tpInt)
                {
                    left = QueryImpl.int2real(left);
                }
                else if (left.type != NodeType.tpReal)
                {
                    throw new CodeGeneratorException("Invalid argument types");
                }
                return(new BinOpNode(NodeType.tpBool, NodeTag.opScanArrayReal4, left, right));

            case NodeType.tpArrayReal8:
                if (left.type == NodeType.tpInt)
                {
                    left = QueryImpl.int2real(left);
                }
                else if (left.type != NodeType.tpReal)
                {
                    throw new CodeGeneratorException("Invalid argument types");
                }
                return(new BinOpNode(NodeType.tpBool, NodeTag.opScanArrayReal8, left, right));

            case NodeType.tpArrayObj:
                return(new BinOpNode(NodeType.tpBool, NodeTag.opScanArrayObj, checkType(NodeType.tpObj, left), right));

            case NodeType.tpArrayStr:
                return(new BinOpNode(NodeType.tpBool, NodeTag.opScanArrayStr, checkType(NodeType.tpStr, left), right));

            case NodeType.tpStr:
                return(new BinOpNode(NodeType.tpBool, NodeTag.opInString, checkType(NodeType.tpStr, left), right));

            case NodeType.tpList:
                return(listToTree(left, (BinOpNode)right));

            default:
                throw new CodeGeneratorException("Invalid argument types");
            }
        }
        private static Node listToTree(Node expr, BinOpNode list)
        {
            BinOpNode tree = null;

            do
            {
                Node    elem = list.right;
                NodeTag cop  = NodeTag.opNop;
                if (elem.type == NodeType.tpUnknown)
                {
                    elem.type = expr.type;
                }
                if (expr.type == NodeType.tpInt)
                {
                    if (elem.type == NodeType.tpReal)
                    {
                        expr = new UnaryOpNode(NodeType.tpReal, NodeTag.opIntToReal, expr);
                        cop  = NodeTag.opRealEq;
                    }
                    else if (elem.type == NodeType.tpInt)
                    {
                        cop = NodeTag.opIntEq;
                    }
                }
                else if (expr.type == NodeType.tpReal)
                {
                    if (elem.type == NodeType.tpReal)
                    {
                        cop = NodeTag.opRealEq;
                    }
                    else if (elem.type == NodeType.tpInt)
                    {
                        cop  = NodeTag.opRealEq;
                        elem = QueryImpl.int2real(elem);
                    }
                }
                else if (expr.type == NodeType.tpDate && elem.type == NodeType.tpDate)
                {
                    cop = NodeTag.opDateEq;
                }
                else if (expr.type == NodeType.tpStr && elem.type == NodeType.tpStr)
                {
                    cop = NodeTag.opStrEq;
                }
                else if (expr.type == NodeType.tpObj && elem.type == NodeType.tpObj)
                {
                    cop = NodeTag.opObjEq;
                }
                else if (expr.type == NodeType.tpBool && elem.type == NodeType.tpBool)
                {
                    cop = NodeTag.opBoolEq;
                }
                if (cop == NodeTag.opNop)
                {
                    throw new CodeGeneratorException("Invalid argument types");
                }
                BinOpNode cmp = new BinOpNode(NodeType.tpBool, cop, expr, elem);
                if (tree == null)
                {
                    tree = cmp;
                }
                else
                {
                    tree = new BinOpNode(NodeType.tpBool, NodeTag.opBoolOr, cmp, tree);
                }
            } while ((list = (BinOpNode)list.left) != null);
            return(tree);
        }