using System; /* * This structure contains the stack effect of a word: number of stack * element consumed on input, and number of stack element produced on * output. */ struct SType { /* * Get number of stack elements consumed on input; this is -1 if * the stack effect is not known. */ internal int DataIn { get { return din; } } /* * Get number of stack elements produced on output; this is -1 if * either the stack effect is not known, or if the word never * exits. */ internal int DataOut { get { return dout; } } /* * Tell whether the stack effect is known. */ internal bool IsKnown { get { return din >= 0; } } /* * Tell whether the stack effect is known and the word never exits. */ internal bool NoExit { get { return din >= 0 && dout < 0; } } int din, dout; internal SType(int din, int dout) { if (din < 0) { din = -1; } if (dout < 0) { dout = -1; } this.din = din; this.dout = dout; } /* * Special value for the unknown stack effect. */ internal static SType UNKNOWN = new SType(-1, -1); /* * Constant for the "blank stack effect". */ internal static SType BLANK = new SType(0, 0); public static bool operator ==(SType s1, SType s2) { return s1.din == s2.din && s1.dout == s2.dout; } public static bool operator !=(SType s1, SType s2) { return s1.din != s2.din || s1.dout != s2.dout; } public override bool Equals(Object obj) { return (obj is SType) && ((SType)obj == this); } public override int GetHashCode() { return din * 31 + dout * 17; } public override string ToString() { if (!IsKnown) { return "UNKNOWN"; } else if (NoExit) { return string.Format("in:{0},noexit", din); } else { return string.Format("in:{0},out:{1}", din, dout); } } /* * Test whether this stack effect is a sub-effect of the provided * stack effect s. Stack effect s1 is a sub-effect of stack-effect * s2 if any of the following holds: * -- s1 and s2 are known, s1.din <= s2.din and s1 does not exit. * -- s1 and s2 are known, s1.din <= s2.din, s1 and s2 exit, * and s1.din - s1.dout == s2.din - s2.dout. */ internal bool IsSubOf(SType s) { if (!IsKnown || !s.IsKnown) { return false; } if (din > s.din) { return false; } if (NoExit) { return true; } if (s.NoExit) { return false; } return (din - dout) == (s.din - s.dout); } }