1using System;
2
3/*
4 * This structure contains the stack effect of a word: number of stack
5 * element consumed on input, and number of stack element produced on
6 * output.
7 */
8
9struct SType {
10
11	/*
12	 * Get number of stack elements consumed on input; this is -1 if
13	 * the stack effect is not known.
14	 */
15	internal int DataIn {
16		get {
17			return din;
18		}
19	}
20
21	/*
22	 * Get number of stack elements produced on output; this is -1 if
23	 * either the stack effect is not known, or if the word never
24	 * exits.
25	 */
26	internal int DataOut {
27		get {
28			return dout;
29		}
30	}
31
32	/*
33	 * Tell whether the stack effect is known.
34	 */
35	internal bool IsKnown {
36		get {
37			return din >= 0;
38		}
39	}
40
41	/*
42	 * Tell whether the stack effect is known and the word never exits.
43	 */
44	internal bool NoExit {
45		get {
46			return din >= 0 && dout < 0;
47		}
48	}
49
50	int din, dout;
51
52	internal SType(int din, int dout)
53	{
54		if (din < 0) {
55			din = -1;
56		}
57		if (dout < 0) {
58			dout = -1;
59		}
60		this.din = din;
61		this.dout = dout;
62	}
63
64	/*
65	 * Special value for the unknown stack effect.
66	 */
67	internal static SType UNKNOWN = new SType(-1, -1);
68
69	/*
70	 * Constant for the "blank stack effect".
71	 */
72	internal static SType BLANK = new SType(0, 0);
73
74	public static bool operator ==(SType s1, SType s2)
75	{
76		return s1.din == s2.din && s1.dout == s2.dout;
77	}
78
79	public static bool operator !=(SType s1, SType s2)
80	{
81		return s1.din != s2.din || s1.dout != s2.dout;
82	}
83
84	public override bool Equals(Object obj)
85	{
86		return (obj is SType) && ((SType)obj == this);
87	}
88
89	public override int GetHashCode()
90	{
91		return din * 31 + dout * 17;
92	}
93
94	public override string ToString()
95	{
96		if (!IsKnown) {
97			return "UNKNOWN";
98		} else if (NoExit) {
99			return string.Format("in:{0},noexit", din);
100		} else {
101			return string.Format("in:{0},out:{1}", din, dout);
102		}
103	}
104
105	/*
106	 * Test whether this stack effect is a sub-effect of the provided
107	 * stack effect s. Stack effect s1 is a sub-effect of stack-effect
108	 * s2 if any of the following holds:
109	 * -- s1 and s2 are known, s1.din <= s2.din and s1 does not exit.
110	 * -- s1 and s2 are known, s1.din <= s2.din, s1 and s2 exit,
111	 *    and s1.din - s1.dout == s2.din - s2.dout.
112	 */
113	internal bool IsSubOf(SType s)
114	{
115		if (!IsKnown || !s.IsKnown) {
116			return false;
117		}
118		if (din > s.din) {
119			return false;
120		}
121		if (NoExit) {
122			return true;
123		}
124		if (s.NoExit) {
125			return false;
126		}
127		return (din - dout) == (s.din - s.dout);
128	}
129}
130