public override CheckTypesResult CheckExprTypeBounds()
        {
            CheckTypesResult result = new CheckTypesResult();

            result.AddMinTypeExprent(value, VarType.Vartype_Bytechar);
            result.AddMaxTypeExprent(value, VarType.Vartype_Int);
            VarType valType = value.GetExprType();

            foreach (List <Exprent> lst in caseValues)
            {
                foreach (Exprent expr in lst)
                {
                    if (expr != null)
                    {
                        VarType caseType = expr.GetExprType();
                        if (!caseType.Equals(valType))
                        {
                            valType = VarType.GetCommonSupertype(caseType, valType);
                            result.AddMinTypeExprent(value, valType);
                        }
                    }
                }
            }
            return(result);
        }
        public override CheckTypesResult CheckExprTypeBounds()
        {
            CheckTypesResult result    = new CheckTypesResult();
            VarType          typeLeft  = left.GetExprType();
            VarType          typeRight = right.GetExprType();

            if (typeLeft.typeFamily > typeRight.typeFamily)
            {
                result.AddMinTypeExprent(right, VarType.GetMinTypeInFamily(typeLeft.typeFamily));
            }
            else if (typeLeft.typeFamily < typeRight.typeFamily)
            {
                result.AddMinTypeExprent(left, typeRight);
            }
            else
            {
                result.AddMinTypeExprent(left, VarType.GetCommonSupertype(typeLeft, typeRight));
            }
            return(result);
        }
        private bool ChangeExprentType(Exprent exprent, VarType newType, int minMax)
        {
            bool res = true;

            switch (exprent.type)
            {
            case Exprent.Exprent_Const:
            {
                ConstExprent constExpr = (ConstExprent)exprent;
                VarType      constType = constExpr.GetConstType();
                if (newType.typeFamily > ICodeConstants.Type_Family_Integer || constType.typeFamily
                    > ICodeConstants.Type_Family_Integer)
                {
                    return(true);
                }
                else if (newType.typeFamily == ICodeConstants.Type_Family_Integer)
                {
                    VarType minInteger = new ConstExprent((int)constExpr.GetValue(), false, null).GetConstType
                                             ();
                    if (minInteger.IsStrictSuperset(newType))
                    {
                        newType = minInteger;
                    }
                }
                goto case Exprent.Exprent_Var;
            }

            case Exprent.Exprent_Var:
            {
                VarVersionPair pair = null;
                if (exprent.type == Exprent.Exprent_Const)
                {
                    pair = new VarVersionPair(((ConstExprent)exprent).id, -1);
                }
                else if (exprent.type == Exprent.Exprent_Var)
                {
                    pair = new VarVersionPair((VarExprent)exprent);
                }
                if (minMax == 0)
                {
                    // min
                    VarType currentMinType = mapExprentMinTypes.GetOrNull(pair);
                    VarType newMinType;
                    if (currentMinType == null || newType.typeFamily > currentMinType.typeFamily)
                    {
                        newMinType = newType;
                    }
                    else if (newType.typeFamily < currentMinType.typeFamily)
                    {
                        return(true);
                    }
                    else
                    {
                        newMinType = VarType.GetCommonSupertype(currentMinType, newType);
                    }
                    Sharpen.Collections.Put(mapExprentMinTypes, pair, newMinType);
                    if (exprent.type == Exprent.Exprent_Const)
                    {
                        ((ConstExprent)exprent).SetConstType(newMinType);
                    }
                    if (currentMinType != null && (newMinType.typeFamily > currentMinType.typeFamily ||
                                                   newMinType.IsStrictSuperset(currentMinType)))
                    {
                        return(false);
                    }
                }
                else
                {
                    // max
                    VarType currentMaxType = mapExprentMaxTypes.GetOrNull(pair);
                    VarType newMaxType;
                    if (currentMaxType == null || newType.typeFamily < currentMaxType.typeFamily)
                    {
                        newMaxType = newType;
                    }
                    else if (newType.typeFamily > currentMaxType.typeFamily)
                    {
                        return(true);
                    }
                    else
                    {
                        newMaxType = VarType.GetCommonMinType(currentMaxType, newType);
                    }
                    Sharpen.Collections.Put(mapExprentMaxTypes, pair, newMaxType);
                }
                break;
            }

            case Exprent.Exprent_Assignment:
            {
                return(ChangeExprentType(((AssignmentExprent)exprent).GetRight(), newType, minMax
                                         ));
            }

            case Exprent.Exprent_Function:
            {
                FunctionExprent func = (FunctionExprent)exprent;
                switch (func.GetFuncType())
                {
                case FunctionExprent.Function_Iif:
                {
                    // FIXME:
                    res = ChangeExprentType(func.GetLstOperands()[1], newType, minMax) & ChangeExprentType
                              (func.GetLstOperands()[2], newType, minMax);
                    break;
                }

                case FunctionExprent.Function_And:
                case FunctionExprent.Function_Or:
                case FunctionExprent.Function_Xor:
                {
                    res = ChangeExprentType(func.GetLstOperands()[0], newType, minMax) & ChangeExprentType
                              (func.GetLstOperands()[1], newType, minMax);
                    break;
                }
                }
                break;
            }
            }
            return(res);
        }
        public override VarType GetExprType()
        {
            VarType exprType = null;

            if (funcType <= Function_Neg || funcType == Function_Ipp || funcType == Function_Ppi ||
                funcType == Function_Imm || funcType == Function_Mmi)
            {
                VarType type1 = lstOperands[0].GetExprType();
                VarType type2 = null;
                if (lstOperands.Count > 1)
                {
                    type2 = lstOperands[1].GetExprType();
                }
                switch (funcType)
                {
                case Function_Imm:
                case Function_Mmi:
                case Function_Ipp:
                case Function_Ppi:
                {
                    exprType = implicitType;
                    break;
                }

                case Function_Bool_Not:
                {
                    exprType = VarType.Vartype_Boolean;
                    break;
                }

                case Function_Shl:
                case Function_Shr:
                case Function_Ushr:
                case Function_Bit_Not:
                case Function_Neg:
                {
                    exprType = GetMaxVarType(new VarType[] { type1 });
                    break;
                }

                case Function_Add:
                case Function_Sub:
                case Function_Mul:
                case Function_Div:
                case Function_Rem:
                {
                    exprType = GetMaxVarType(new VarType[] { type1, type2 });
                    break;
                }

                case Function_And:
                case Function_Or:
                case Function_Xor:
                {
                    if (type1.type == ICodeConstants.Type_Boolean & type2.type == ICodeConstants.Type_Boolean)
                    {
                        exprType = VarType.Vartype_Boolean;
                    }
                    else
                    {
                        exprType = GetMaxVarType(new VarType[] { type1, type2 });
                    }
                    break;
                }
                }
            }
            else if (funcType == Function_Cast)
            {
                exprType = lstOperands[1].GetExprType();
            }
            else if (funcType == Function_Iif)
            {
                Exprent param1    = lstOperands[1];
                Exprent param2    = lstOperands[2];
                VarType supertype = VarType.GetCommonSupertype(param1.GetExprType(), param2.GetExprType
                                                                   ());
                if (param1.type == Exprent.Exprent_Const && param2.type == Exprent.Exprent_Const &&
                    supertype.type != ICodeConstants.Type_Boolean && VarType.Vartype_Int.IsSuperset
                        (supertype))
                {
                    exprType = VarType.Vartype_Int;
                }
                else
                {
                    exprType = supertype;
                }
            }
            else if (funcType == Function_Str_Concat)
            {
                exprType = VarType.Vartype_String;
            }
            else if (funcType >= Function_Eq || funcType == Function_Instanceof)
            {
                exprType = VarType.Vartype_Boolean;
            }
            else if (funcType >= Function_Array_Length)
            {
                exprType = VarType.Vartype_Int;
            }
            else
            {
                exprType = Types[funcType - Function_I2l];
            }
            return(exprType);
        }