public VarInfo Merge(VarInfo other)
 {
     if (other.Type == Type)
     {
         if (other.Value != Value)
         {
             return(new VarInfo(Flag.NAC));
         }
         return(this);
     }
     if (IsUndef && other.IsConst)
     {
         return(other.Copy());
     }
     if (IsUndef && other.IsNac)
     {
         return(other.Copy());
     }
     if (IsNac)
     {
         return(this.Copy());
     }
     if (other.IsNac)
     {
         return(other.Copy());
     }
     return(this.Copy());
 }
 public int?Compare(VarInfo other)
 {
     if (Type == other.Type)
     {
         if (Type == Flag.Const)
         {
             if (Value == other.Value)
             {
                 return(0);
             }
             else
             {
                 return(null);
             }
         }
         return(0);
     }
     if (Type == Flag.UNDEF)
     {
         return(1);
     }
     if (Type == Flag.NAC)
     {
         return(-1);
     }
     if (other.Type == Flag.NAC)
     {
         return(1);
     }
     return(-1);
 }
        public VarInfoTable Transfer(BasicBlock basicBlock, VarInfoTable input, ILatticeOperations <VarInfoTable> ops)
        {
            var table = input.Copy();

            VarInfo Get(Expr e)
            {
                if (e is IntConst c)
                {
                    return(new VarInfo(VarInfo.Flag.Const, c.Num));
                }
                if (e is Var v)
                {
                    return(table[v.Id].Copy());
                }
                return(new VarInfo(VarInfo.Flag.NAC));
            }

            foreach (var line in basicBlock.CodeList.OfType <Assign>())
            {
                if (line.Left is null)
                {
                    table[line.Result.Id] = Get(line.Right);
                }
                else
                {
                    var vi1 = Get(line.Right);
                    var vi2 = Get(line.Left);

                    table[line.Result.Id] = VarInfo.MergeBin(vi1, vi2, line.Operation);
                }
            }
            return(table);
        }
        public static VarInfo MergeBin(VarInfo vi1, VarInfo vi2, OpCode?op)
        {
            if (vi1.IsConst && vi2.IsConst)
            {
                Func <int, int, int> f = (x, y) => x + y;

                if (op == OpCode.Div)
                {
                    f = (x, y) => x / y;
                }
                if (op == OpCode.Equal)
                {
                    f = (x, y) => x == y ? 1 : 0;
                }
                if (op == OpCode.Greater)
                {
                    f = (x, y) => x > y ? 1 : 0;
                }
                if (op == OpCode.GreaterEq)
                {
                    f = (x, y) => x >= y ? 1 : 0;
                }
                if (op == OpCode.Less)
                {
                    f = (x, y) => x < y ? 1 : 0;
                }
                if (op == OpCode.LessEq)
                {
                    f = (x, y) => x <= y ? 1 : 0;
                }
                if (op == OpCode.Minus)
                {
                    f = (x, y) => x - y;
                }
                if (op == OpCode.Mul)
                {
                    f = (x, y) => x * y;
                }
                if (op == OpCode.Plus)
                {
                    f = (x, y) => x + y;
                }

                return(new VarInfo(Flag.Const, f(vi1.Value.Value, vi2.Value.Value)));
            }
            if (vi1.IsNac || vi2.IsNac)
            {
                return(new VarInfo(Flag.NAC));
            }
            return(new VarInfo(Flag.UNDEF));
        }
        public Operations(TACode code)
        {
            Lower = new VarInfoTable(code);
            var keys = Lower.Keys.ToArray();

            foreach (var k in keys)
            {
                Lower[k] = new VarInfo(VarInfo.Flag.NAC);
            }

            Upper = new VarInfoTable(code);
            foreach (var k in keys)
            {
                Upper[k] = new VarInfo(VarInfo.Flag.UNDEF);
            }
        }