xref: /freebsd/contrib/bearssl/T0/SType.cs (revision 42249ef2)
1 using 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 
9 struct 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